package cqrtplm.service.impl;

import java.math.BigInteger;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.IterUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.googlecode.aviator.AviatorEvaluator;
import com.googlecode.aviator.Expression;
import com.hustcad.plm.basic.dto.TyplmCommonQueryDTO;
import com.hustcad.plm.basic.util.TyplmLoggerUtil;
import com.hustcad.plm.pdm.common.model.vo.BusinessObjectVO;
import com.hustcad.plm.pdm.common.model.vo.iteration.CommonIteratorVO;
import com.hustcad.plm.pdm.ec.module.dto.ECObjData;
import com.hustcad.plm.pdm.ec.module.vo.ECLinkObjDataCommonVO;
import com.hustcad.plm.pdm.ec.module.vo.ECObjDataVO;
import com.hustcad.plm.pdm.ec.service.TyplmEcAgainstDataService;
import com.hustcad.plm.pdm.file.handler.response.ResponseResult;
import com.hustcad.plm.pdm.flowbusiness.model.entity.FlowChgFormView;
import com.hustcad.plm.pdm.folder.model.dto.filter.TySubFolderFilterQuery;
import com.hustcad.plm.pdm.folder.model.dto.filter.TyplmFolderObjDTO;
import com.hustcad.plm.pdm.folder.service.search.TyplmSubFilterObjectService;
import com.hustcad.plm.pdm.iba.model.dto.SaveObjIBADTO;
import com.hustcad.plm.pdm.iteration.controller.TyplmIterationController;
import com.hustcad.plm.pdm.middle.partbom.adapter.TyplmPartBomAdapter;
import com.hustcad.plm.pdm.middle.partbom.service.TyplmPdmPartService;
import com.hustcad.plm.pdm.doc.vo.DocDetails;
import com.hustcad.plm.pdm.flowbusiness.model.entity.FlowObject;
import com.hustcad.plm.pdm.flowbusiness.model.entity.WorkFlowObjectPackage;
import com.hustcad.plm.pdm.flowbusiness.service.TyplmPBOProcessHistoryQueryService;
import com.hustcad.plm.pdm.iba.service.impl.TyplmAttributeServiceImpl;
import com.hustcad.plm.pdm.partbom.controller.TyplmBomController;
import com.hustcad.plm.pdm.partbom.controller.TyplmPartController;
import com.hustcad.plm.pdm.partbom.dto.BomAddBatchCheckDTO;
import com.hustcad.plm.pdm.partbom.dto.PartBomTreeNode;
import com.hustcad.plm.pdm.partbom.dto.PartBomView;
import com.hustcad.plm.pdm.partbom.dto.PartUsageLink;
import com.hustcad.plm.pdm.partbom.service.TyplmPartService;
import com.hustcad.plm.pdm.partbom.service.TyplmPartRelObjectService;
import com.hustcad.plm.pdm.partbom.service.TyplmPartUsageLinkService;
import com.hustcad.plm.pdm.partbom.service.view.TyplmViewDefService;
import com.hustcad.plm.pdm.partbom.vo.PartDetailsVO;
import com.hustcad.plm.pdm.user.model.dto.PdmUserDTO;
import com.hustcad.plm.pdm.user.service.TyplmUserService;
import com.hustcad.plm.pdm.workflow.model.dto.AdvancedFlowContainerCondition;
import com.hustcad.plm.pdm.workflow.model.entity.FlowTaskRecord;
import com.hustcad.plm.pdm.workflow.model.entity.UserTaskDTO;
import com.hustcad.plm.pdm.workflow.model.entity.WorkFlow;
import com.hustcad.plm.pdm.workflow.model.entity.WorkFlowContainerView;
import com.hustcad.plm.pdm.workflow.model.vo.AdvancedFlowContainerVO;
import com.hustcad.plm.pdm.workflow.model.vo.FlowObjectDetailInfoVO;
import com.hustcad.plm.pdm.workflow.service.TyplmFlowTaskUserService;
import com.hustcad.plm.pdm.workflow.service.TyplmWorkFlowContainerService;
import com.ty.basic.constant.TableTypeConstrant;
import com.ty.basic.dto.constraint.IbaDTO;
import com.ty.basic.entity.CTyEntityBaseDO;
import com.ty.basic.entity.IdentifierEntity;
import com.ty.basic.entity.org.UserDO;
import com.ty.basic.entity.part.PartDO;
import com.ty.basic.entity.part.PartMasterDO;
import com.ty.basic.entity.view.ViewDefDO;
import com.ty.basic.service.snow.SnowflakeIdComponent;
import com.ty.basic.session.TyAccountContext;
import cqrtplm.constant.IpAddressConstant;
import cqrtplm.constant.RTErrorCodeEnum;
import cqrtplm.constant.RTPlmConstant;
import cqrtplm.dto.*;

import cqrtplm.dto.query.CrmApiQueryDTO;
import cqrtplm.dto.thirdPartyAPI.*;
import cqrtplm.entity.*;
import cqrtplm.enums.DrawingEnums;
import cqrtplm.mapper.*;
import cqrtplm.service.*;
import cqrtplm.vo.CrmApiResponseVO;
import cqrtplm.vo.MomApiResponseVO;
import cqrtplm.vo.RtCertFiledVO;
import cqrtplm.vo.RtCfgDspfDemandMainVO;
import cqrtplm.vo.TransitOrderResponseVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import com.ty.basic.entity.part.PartUsageLinkDO;

import javax.annotation.Resource;
import javax.validation.constraints.NotNull;

/**
 * 需求主表Service业务层处理
 *
 * @author 江小雄
 * @date 2025-07-10
 */
@Service
@Slf4j
public class RtCfgDspfDemandMainServiceImpl implements IRtCfgDspfDemandMainService {

    public String flowJson = "{\"keyWord\":\"WT202508180013\",\"myCreate\":false,\"myJoin\":false,\"myWatch\":false,\"myManage\":false,\"workflowIdSet\":[\"720049214094950400\"],\"includeTY\":0,\"type\":\"\",\"statusOutZero\":\"\",\"emergencydegree\":\"\",\"creatorOid\":\"\",\"operatorOid\":\"\",\"remark\":\"\",\"createStartDate\":\"\",\"createEndDate\":\"\",\"startStartDate\":\"\",\"startEndDate\":\"\",\"completeStartDate\":\"\",\"completeEndDate\":\"\",\"containerSet\":[{\"oid\":\"707053057766981632\",\"otype\":\"ty.inteplm.product.CTyPDMLinkProduct\"},{\"oid\":\"\",\"otype\":\"ty.inteplm.domain.CTyOrgContainer\"}],\"pageNum\":1,\"pageSize\":20,\"columns\":[{\"propertyName\":\"code\",\"displayName\":\"流程编号\",\"masterProperty\":false,\"fixed\":\"left\",\"width\":\"180\",\"sortable\":false,\"fieldList\":[],\"virtual\":false,\"foreignColumnMaster\":false,\"canNotRemove\":false,\"enum\":false},{\"propertyName\":\"name\",\"displayName\":\"流程名称\",\"masterProperty\":false,\"fixed\":\"left\",\"width\":\"180\",\"sortable\":false,\"fieldList\":[],\"virtual\":false,\"foreignColumnMaster\":false,\"canNotRemove\":false,\"enum\":false},{\"propertyName\":\"remark\",\"displayName\":\"流程描述\",\"masterProperty\":false,\"width\":\"120\",\"sortable\":false,\"fieldList\":[],\"virtual\":false,\"foreignColumnMaster\":false,\"canNotRemove\":false,\"enum\":false},{\"propertyName\":\"workflowName\",\"displayName\":\"流程模板\",\"masterProperty\":false,\"width\":\"160\",\"sortable\":false,\"fieldList\":[],\"virtual\":false,\"foreignColumnMaster\":false,\"canNotRemove\":false,\"enum\":false},{\"propertyName\":\"statusName\",\"displayName\":\"流程状态\",\"masterProperty\":false,\"width\":\"80\",\"sortable\":false,\"fieldList\":[],\"virtual\":false,\"foreignColumnMaster\":false,\"canNotRemove\":false,\"enum\":false},{\"propertyName\":\"taskName\",\"displayName\":\"当前节点\",\"masterProperty\":false,\"width\":\"80\",\"sortable\":false,\"fieldList\":[],\"virtual\":false,\"foreignColumnMaster\":false,\"canNotRemove\":false,\"enum\":false},{\"propertyName\":\"taskUserName\",\"displayName\":\"未执行人\",\"masterProperty\":false,\"width\":\"100\",\"sortable\":false,\"fieldList\":[],\"virtual\":false,\"foreignColumnMaster\":false,\"canNotRemove\":false,\"enum\":false},{\"propertyName\":\"creatorName\",\"displayName\":\"发起者\",\"masterProperty\":false,\"width\":\"100\",\"sortable\":false,\"fieldList\":[],\"virtual\":false,\"foreignColumnMaster\":false,\"canNotRemove\":false,\"enum\":false},{\"propertyName\":\"createStamp\",\"displayName\":\"发起时间\",\"masterProperty\":false,\"width\":\"140\",\"sortable\":false,\"fieldList\":[],\"virtual\":false,\"foreignColumnMaster\":false,\"canNotRemove\":false,\"enum\":false},{\"propertyName\":\"type\",\"displayName\":\"流程类型\",\"masterProperty\":false,\"width\":\"80\",\"sortable\":false,\"fieldList\":[],\"virtual\":false,\"foreignColumnMaster\":false,\"canNotRemove\":false,\"enum\":false}]}";

    @Resource
    private RtCfgDspfDemandMainMapper rtCfgDspfDemandMainMapper;
    @Resource
    private TyplmWorkFlowContainerService typlmWorkFlowContainerService;
    @Resource
    private RtCfgStatusInfoMapper rtCfgStatusInfoMapper;
    @Resource
    private TyplmPBOProcessHistoryQueryService typlmProcessQueryService;
    @Resource
    private RtCfgDemandOrdersMapper rtCfgDemandOrdersMapper;
    @Resource
    private SnowflakeIdComponent snowflakeIdComponent;
    @Resource
    private RtCfgBomService rtCfgBomService;
    @Resource
    private DspfDemandDevplanMapper dspfDemandDevplanMapper;
    @Resource
    private RtCfgBomMapper rtCfgBomMapper;
    @Resource
    private TyplmPartRelObjectService typlmPartRelObjectService;
    @Resource
    private TyplmFlowTaskUserService typlmFlowTaskUserService;
    @Resource
    private TyplmUserService typlmUserService;
    @Resource
    private TyplmPdmPartService typlmPdmPartService;
    @Resource
    private TyplmPartService typlmPartService;
    @Resource
    private DspfMbomDetailMapper dspfMbomDetailMapper;
    @Resource
    private DspfMbomBomMapper dspfMbomBomMapper;
    @Resource
    private TyplmSubFilterObjectService typlmSubFilterObjectService;
    @Resource
    private TyplmIterationController typlmIterationController;
    @Resource
    private TyplmBomController typlmBomController;
    @Resource
    private TyplmEcAgainstDataService typlmEcAgainstDataService;
    @Resource
    private RTChangeMapper rtChangeMapper;
    @Resource
    private TyplmPartUsageLinkService typlmPartUsageLinkService;
    @Resource
    private PlatformTransactionManager transactionManager;
    @Resource
    private TyplmViewDefService typlmViewDefService;
    @Resource
    private RTPartMapper rtPartMapper;
    @Resource
    private TyplmPartBomAdapter typlmPartBomAdapter;
    @Resource
    private RatoCpytMapper ratoCpytMapper;
    @Resource
    private IRtCfgSerialNumberService iRtCfgSerialNumberService;
    @Autowired
    private RtCertCombCertService rtCertCombCertService;
    @Resource
    private RtCertFiledMapper rtCertFiledMapper;
    @Resource
    private InterfaceLogRecordMapper interfaceLogRecordMapper;
    @Resource
    private RtZdService rtZdService;
    @Resource
    private RtCertFiledService rtCertFiledService;


    @Autowired
    private CrmApiService crmApiService;
    @Resource
    private MomApiService momApiService;
    @Resource
    private SapApiService sapApiService;


    /**
     * 查询需求主表
     *
     * @param kid 需求主表主键
     * @return 需求主表
     */
    @Override
    public RtCfgDspfDemandMain selectRtCfgDspfDemandMainByKid(String kid) {
        return rtCfgDspfDemandMainMapper.selectRtCfgDspfDemandMainByKid(kid);
    }

    /**
     * 查询需求主表列表
     *
     * @param rtCfgDspfDemandMain 需求主表
     * @return 需求主表
     */
    @Override
    public List<RtCfgDspfDemandMain> selectRtCfgDspfDemandMainList(RtCfgDspfDemandMain rtCfgDspfDemandMain) {
        return rtCfgDspfDemandMainMapper.selectRtCfgDspfDemandMainList(rtCfgDspfDemandMain);
    }

    /**
     * 新增需求主表
     *
     * @param rtCfgDspfDemandMain 需求主表
     * @return 结果
     */
    @Override
    public int insertRtCfgDspfDemandMain(RtCfgDspfDemandMain rtCfgDspfDemandMain) {
        return rtCfgDspfDemandMainMapper.insertRtCfgDspfDemandMain(rtCfgDspfDemandMain);
    }

    /**
     * 修改需求主表
     *
     * @param rtCfgDspfDemandMain 需求主表
     * @return 结果
     */
    @Override
    public int updateRtCfgDspfDemandMain(RtCfgDspfDemandMain rtCfgDspfDemandMain) {
        return rtCfgDspfDemandMainMapper.updateRtCfgDspfDemandMain(rtCfgDspfDemandMain);
    }

    /**
     * 批量删除需求主表
     *
     * @param kids 需要删除的需求主表主键
     * @return 结果
     */
    @Override
    public int deleteRtCfgDspfDemandMainByKids(String[] kids) {
        return rtCfgDspfDemandMainMapper.deleteRtCfgDspfDemandMainByKids(kids);
    }

    /**
     * 删除需求主表信息
     *
     * @param kid 需求主表主键
     * @return 结果
     */
    @Override
    public int deleteRtCfgDspfDemandMainByKid(String kid) {
        return rtCfgDspfDemandMainMapper.deleteRtCfgDspfDemandMainByKid(kid);
    }

    @Override
    public PageInfo<RtCfgDspfDemandMainVO> selectPageList(RtCfgDspfDemandMainQueryDTO queryDTO, int pageNum,
                                                          int pageSize) {

        PageHelper.startPage(pageNum, pageSize);
        List<RtCfgDspfDemandMainVO> list = rtCfgDspfDemandMainMapper.selectPageList(queryDTO);
        list = this.getFlowMessage(list);
        return new PageInfo<RtCfgDspfDemandMainVO>(list);
    }

    /**
     * 调用系统底层方法查询需求状态表流程相关信息
     *
     * @param list
     * @return
     */
    private List<RtCfgDspfDemandMainVO> getFlowMessage(List<RtCfgDspfDemandMainVO> list) {
        if (IterUtil.isNotEmpty(list)) {
            list.stream().forEach(i -> {
                String oid = i.getOid();
                if (!Integer.valueOf(2).equals(i.getStatus())) {
                    String flowCode = this.getFlowCode(oid);
                    i.setFlowCode(flowCode);
                    //根据流程编码获取流程相关信息
                    //                        AdvancedFlowContainerCondition condition = JSONUtil.toBean(flowJson,AdvancedFlowContainerCondition.class);
                    //                        condition.setKeyWord(latest.getCode());
                    //                        PageInfo<AdvancedFlowContainerVO> pageInfo = this.typlmWorkFlowContainerService.advancedQueryListPage(condition);
                    //                        String taskUserName = pageInfo.getList().get(0).getTaskUserName();
                }
            });
        }
        return list;
    }

    /**
     * 调用底层方法获取flowCode
     *
     * @param oid
     * @return
     */
    private String getFlowCode(String oid) {
        TyplmCommonQueryDTO queryDTO = new TyplmCommonQueryDTO();
        if (StrUtil.isNotEmpty(oid)) {
            queryDTO.setOid(new BigInteger(oid));
            queryDTO.setQueryType("currentVersion");
            queryDTO.setOtype("ty.inteplm.part.CTyPart");
            try {
                List<FlowObjectDetailInfoVO> flowObjectDetailInfoList = typlmProcessQueryService
                        .queryProcessListByObject(
                                queryDTO);
                if (IterUtil.isNotEmpty(flowObjectDetailInfoList)) {
                    // 根据 createTime 排序，倒序排列，最新的在最前面
                    flowObjectDetailInfoList.sort((o1, o2) -> o2.getCreateTime().compareTo(o1.getCreateTime()));
                    // 获取最新的一个
                    FlowObjectDetailInfoVO latest = flowObjectDetailInfoList.isEmpty() ? null : flowObjectDetailInfoList
                            .get(0);
                    return latest.getCode();
                }
            } catch (Exception e) {

            }

        }
        return "";
    }


    @Override
    public PageInfo<RtCfgDspfDemandMainVO> selectPageListDaiban(RtCfgDspfDemandMainQueryDTO queryDTO, int pageNum,
                                                                int pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        List<RtCfgDspfDemandMainVO> list = rtCfgDspfDemandMainMapper.selectPageListDaiban(queryDTO);
        return new PageInfo<RtCfgDspfDemandMainVO>(list);
    }

    /**
     * 需求状态表需求创建流程审批方法
     *
     * @param finalWorkFlowContainerId
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void workFlowXqsp(BigInteger finalWorkFlowContainerId) throws JsonProcessingException {
        WorkFlowContainerView workFlowContainerView = typlmWorkFlowContainerService
                .getWorkFlowContainerDetailByPrimaryKey(
                        finalWorkFlowContainerId);
        List<IdentifierEntity> flowList = new ArrayList<>();
        if ((workFlowContainerView instanceof WorkFlowObjectPackage)) {
            log.info("当前流程属于普通流程----》需求状态表流程创建");
            WorkFlowObjectPackage workFlowObjectPackage = (WorkFlowObjectPackage) workFlowContainerView;
            List<FlowObject> flowObjectList = workFlowObjectPackage.getFlowObjectList();
            if (CollUtil.isNotEmpty(flowObjectList)) {
                flowList = flowObjectList.stream().map(
                        m -> new IdentifierEntity(m.getRefObjectOid(), m.getRefObjectOtype())).distinct().collect(
                        Collectors.toList());
                BigInteger oid = flowList.get(0).getOid();

                RtCfgStatusDTO rtCfgStatusDTO = new RtCfgStatusDTO();
                rtCfgStatusDTO.setOid(oid.toString());
                RtCfgStatusInfoDO rtCfgStatusInfoDO = rtCfgStatusInfoMapper.selectByStatusCode(rtCfgStatusDTO);
                if (ObjectUtil.isNotEmpty(rtCfgStatusInfoDO)) {
                    rtCfgBomService.getRtCfgBuildBOMDetailVoid(rtCfgStatusInfoDO);
                    //根据oid修改需求状态表审批状态为审批中
                    rtCfgStatusInfoMapper.updateByOid(oid);
                }

            }

        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void workFlowPqsp(BigInteger finalWorkFlowContainerId) {
        WorkFlowContainerView workFlowContainerView = typlmWorkFlowContainerService
                .getWorkFlowContainerDetailByPrimaryKey(
                        finalWorkFlowContainerId);
        List<IdentifierEntity> flowList = new ArrayList<>();
        if ((workFlowContainerView instanceof WorkFlowObjectPackage)) {
            log.info("当前流程属于普通流程----》需求状态表片区经理审核");
            WorkFlowObjectPackage workFlowObjectPackage = (WorkFlowObjectPackage) workFlowContainerView;
            List<FlowObject> flowObjectList = workFlowObjectPackage.getFlowObjectList();
            if (CollUtil.isNotEmpty(flowObjectList)) {
                flowList = flowObjectList.stream().map(
                        m -> new IdentifierEntity(m.getRefObjectOid(), m.getRefObjectOtype())).distinct().collect(
                        Collectors.toList());
                BigInteger oid = flowList.get(0).getOid();
                /*
                 * 片区经理审核逻辑
                 *   1.根据oid查询需求状态表信息
                 *   2.将查询出的信息插入需求排程表
                 * */
                RtCfgStatusDTO rtCfgStatusDTO = new RtCfgStatusDTO();
                rtCfgStatusDTO.setOid(String.valueOf(oid));
                RtCfgStatusInfoDO rtCfgStatusInfoDO = rtCfgStatusInfoMapper.selectByStatusCode(rtCfgStatusDTO);
                String flowCode = this.getFlowCode(oid.toString());
                RtCfgDemandOrders rtCfgDemandOrders = new RtCfgDemandOrders(rtCfgStatusInfoDO, flowCode);
                rtCfgDemandOrders.setId(snowflakeIdComponent.getInstance().nextId().toString());
                //                try{
                rtCfgDemandOrdersMapper.insertRtCfgDemandOrders(rtCfgDemandOrders);
                //                }catch (Exception e){
                //                    e.printStackTrace();
                //                }

            }

        }
    }

    @Override
    public Map<String, Integer> workIsCrew(BigInteger finalWorkFlowContainerId, String nodeids) {
        Map<String, Integer> hashMap = new HashMap<>();
        WorkFlowContainerView workFlowContainerView = typlmWorkFlowContainerService
                .getWorkFlowContainerDetailByPrimaryKey(
                        finalWorkFlowContainerId);
        List<IdentifierEntity> flowList = new ArrayList<>();
        if ((workFlowContainerView instanceof WorkFlowObjectPackage)) {
            log.info("当前流程属于普通流程----》需求状态表并行(终端,动力,传动)");
            WorkFlowObjectPackage workFlowObjectPackage = (WorkFlowObjectPackage) workFlowContainerView;
            List<FlowObject> flowObjectList = workFlowObjectPackage.getFlowObjectList();
            if (CollUtil.isNotEmpty(flowObjectList)) {
                flowList = flowObjectList.stream().map(
                        m -> new IdentifierEntity(m.getRefObjectOid(), m.getRefObjectOtype())).distinct().collect(
                        Collectors.toList());
                BigInteger oid = flowList.get(0).getOid();
                /*
                 * 是否机组（终端）、动力、传动判断逻辑
                 *   1.根据oid查询需求排程表信息
                 *   2.根据排程表信息查询是否选择机组（终端）、动力、传动
                 *   3.根据需求状态表开发令查询产线信息来控制面板贴花与面板电气节点信息
                 * */
                RtCfgStatusDTO rtCfgStatusDTO = new RtCfgStatusDTO();
                rtCfgStatusDTO.setOid(String.valueOf(oid));
                RtCfgStatusInfoDO rtCfgStatusInfoDO = rtCfgStatusInfoMapper.selectByStatusCode(rtCfgStatusDTO);

                DspfDemandDevplanDO dspfDemandDevplanDO = dspfDemandDevplanMapper.selectDspfDemandDevplanByStatusId(
                        rtCfgStatusInfoDO.getStatusid());
                if (ObjectUtil.isEmpty(dspfDemandDevplanDO)) {
                    throw RTErrorCodeEnum.STATUS_INFO_CONTENT_IS_NULL.getException("请先进行排程操作");
                }
                Integer isAllocate = dspfDemandDevplanDO.getIsAllocate();
                if (isAllocate == 0) {
                    throw RTErrorCodeEnum.STATUS_INFO_CONTENT_IS_NULL.getException("请先进行人员分配");
                }
                //根据排程所填写的动力、机组、传动管理员来控制流程节点应该走哪一个分支
                Integer isParallel = this.setProcessNodes(dspfDemandDevplanDO, nodeids, workFlowContainerView);
                hashMap.put("isParallel", isParallel);

                //根据产线信息赋值节点变量
                String devcode = rtCfgStatusInfoDO.getDevcode();
                if (StrUtil.isEmpty(devcode)) {
                    throw RTErrorCodeEnum.STATUS_INFO_CONTENT_IS_NULL.getException("此需求状态表无开发令，请先检查");
                } else {
                    //根据产线决定流程节点分支走向
                    String line = devcode.substring(0, 1);
                    if ("Y".equals(line) || "W".equals(line) || "X".equals(line)) {
                        hashMap.put("isProductline", 1);
                    } else {
                        hashMap.put("isProductline", 2);
                    }
                }
            }
        }

        //需求状态表变更流程
        if (workFlowContainerView instanceof FlowChgFormView) {
            log.info("当前流程属于变更请求流程");
            List<ECLinkObjDataCommonVO> ecLinkObjDataCommonVOS = typlmEcAgainstDataService
                    .batchGetAffectedObjectListByOids(
                            Collections.singletonList(workFlowContainerView.getBaseObjectOid()),
                            workFlowContainerView.getBaseObjectOtype());
            if (CollUtil.isNotEmpty(ecLinkObjDataCommonVOS)) {
                flowList = ecLinkObjDataCommonVOS.stream().map(m -> new IdentifierEntity(m.getOid(), m.getOtype()))
                        .distinct().collect(Collectors.toList());
                BigInteger oid = flowList.get(0).getOid();
                RtCfgStatusDTO rtCfgStatusDTO = new RtCfgStatusDTO();
                rtCfgStatusDTO.setOid(String.valueOf(oid));
                RtCfgStatusInfoDO rtCfgStatusInfoDO = rtCfgStatusInfoMapper.selectByStatusCode(rtCfgStatusDTO);

                DspfDemandDevplanDO dspfDemandDevplanDO = dspfDemandDevplanMapper.selectDspfDemandDevplanByStatusId(
                        rtCfgStatusInfoDO.getStatusid());
                if (ObjectUtil.isEmpty(dspfDemandDevplanDO)) {
                    throw RTErrorCodeEnum.STATUS_INFO_CONTENT_IS_NULL.getException("请先进行排程操作");
                }
                Integer isAllocate = dspfDemandDevplanDO.getIsAllocate();
                if (isAllocate == 0) {
                    throw RTErrorCodeEnum.STATUS_INFO_CONTENT_IS_NULL.getException("请先进行人员分配");
                }
                //根据排程所填写的动力、机组、传动管理员来控制流程节点应该走哪一个分支
                Integer isParallel = this.setProcessNodes(dspfDemandDevplanDO, nodeids, workFlowContainerView);
                hashMap.put("isParallel", isParallel);

                //根据产线信息赋值节点变量
                String devcode = rtCfgStatusInfoDO.getDevcode();
                if (StrUtil.isEmpty(devcode)) {
                    throw RTErrorCodeEnum.STATUS_INFO_CONTENT_IS_NULL.getException("此需求状态表无开发令，请先检查");
                } else {
                    //根据产线决定流程节点分支走向
                    String line = devcode.substring(0, 1);
                    if ("Y".equals(line) || "W".equals(line) || "X".equals(line)) {
                        hashMap.put("isProductline", 1);
                    } else {
                        hashMap.put("isProductline", 2);
                    }
                }
            }

        }

        return hashMap;
    }

    private Integer setProcessNodes(DspfDemandDevplanDO dspfDemandDevplanDO, String nodeIds,
                                    WorkFlowContainerView workFlowContainerView) {

        /*
         * 状态室分配逻辑
         *   1.根据排程页面选择的机组、动力、传动管理员来设置节点审批人
         *   2.根据排程选择的机组、动力、传动管理员来设置走单节点还是并行节点
         *   3.在设置节点并行时还需判断BOM结构中包含的（终端、动力、传动）
         * */
        String crewAdministrator = dspfDemandDevplanDO.getCrewAdministrator();
        String powerAdministrator = dspfDemandDevplanDO.getPowerAdministrator();
        String tranAdministrator = dspfDemandDevplanDO.getTranAdministrator();

        if (StrUtil.isEmpty(nodeIds)) {
            throw RTErrorCodeEnum.STATUS_INFO_CONTENT_IS_NULL.getException("机组动力选择判断异常,请先配置节点");
        }

        // 先清空节点执行人，然后在设置排程时选择节点的执行人
        List<UserTaskDTO> userTaskList = workFlowContainerView.getUserTaskList();
        //key为节点id，值为节点用户
        Map<String, UserTaskDTO> userTaskMap = userTaskList.stream()
                .collect(Collectors.toMap(UserTaskDTO::getId, item -> item));
        if (StrUtil.isNotEmpty(nodeIds)) {
            ProcessNodeDTO processNodeDTO = JSONUtil.toBean(nodeIds, ProcessNodeDTO.class);
            List<String> list = processNodeDTO.getDljzcdList();
            for (int i = 0; i < list.size(); i++) {
                UserTaskDTO userTaskDTO = userTaskMap.get(list.get(i));
                userTaskDTO.getUserList().clear();
                log.info("角色分支判断：清空节点 {} 的执行人", list.get(i));
                //如果bom结构中包含终端，设置终端平台节点审批人
                if ("Activity_1umeifb".equals(list.get(i))) {
                    if (StrUtil.isNotEmpty(crewAdministrator)) {
                        userTaskDTO.setUserList(this.getPdmUserDTOS(Arrays.asList(crewAdministrator)));
                        userTaskList.add(userTaskDTO);
                    }
                }

                //如果bom结构中包含动力，设置动力平台节点审批人
                if ("Activity_144fokd".equals(list.get(i))) {
                    if (StrUtil.isNotEmpty(powerAdministrator)) {
                        userTaskDTO.setUserList(this.getPdmUserDTOS(Arrays.asList(powerAdministrator)));
                        userTaskList.add(userTaskDTO);
                    }
                }
                //如果bom结构中包含传动，设置传动平台节点审批人
                if ("Activity_0tgtriy".equals(list.get(i))) {
                    if (StrUtil.isNotEmpty(tranAdministrator)) {
                        userTaskDTO.setUserList(this.getPdmUserDTOS(Arrays.asList(tranAdministrator)));
                        userTaskList.add(userTaskDTO);
                    }
                }

            }
        }
        workFlowContainerView.setUserTaskList(userTaskList);
        // 更新用户任务列表
        this.typlmFlowTaskUserService.updateUserTaskList(workFlowContainerView);

        //设置该走那条分支线
        if (StrUtil.isNotEmpty(crewAdministrator) && StrUtil.isNotEmpty(powerAdministrator) && StrUtil.isNotEmpty(
                tranAdministrator)) {
            return 7;
        } else if (StrUtil.isNotEmpty(crewAdministrator) && StrUtil.isNotEmpty(tranAdministrator)) {
            return 6;
        } else if (StrUtil.isNotEmpty(powerAdministrator) && StrUtil.isNotEmpty(tranAdministrator)) {
            return 5;
        } else if (StrUtil.isNotEmpty(crewAdministrator) && StrUtil.isNotEmpty(powerAdministrator)) {
            return 4;
        } else if (StrUtil.isNotEmpty(tranAdministrator)) {
            return 3;
        } else if (StrUtil.isNotEmpty(powerAdministrator)) {
            return 2;
        } else if (StrUtil.isNotEmpty(crewAdministrator)) {
            return 1;
        } else {
            throw RTErrorCodeEnum.STATUS_INFO_CONTENT_IS_NULL.getException("机组动力选择判断异常,请先分配人员");
        }
    }

    /**
     * 获取List<PdmUserDTO> 参与者信息
     *
     * @param userNameList
     * @return
     */
    public List<PdmUserDTO> getPdmUserDTOS(List<String> userNameList) {
        List<UserDO> userDOS = typlmUserService.queryUserByNameList(userNameList);
        List<PdmUserDTO> pdmUserDTOList = new ArrayList<>();
        if (CollUtil.isNotEmpty(userDOS)) {
            pdmUserDTOList = convertToPdmUserDTO(userDOS);
        }
        return pdmUserDTOList;
    }

    public List<PdmUserDTO> convertToPdmUserDTO(List<UserDO> userDOList) {
        List<PdmUserDTO> userList = new ArrayList<>();
        if (CollUtil.isEmpty(userDOList)) {
            return userList;
        }
        for (UserDO userDO : userDOList) {
            PdmUserDTO pdmUserDTO = convertPdmUserDTO(userDO);
            userList.add(pdmUserDTO);
        }
        return userList;
    }

    private PdmUserDTO convertPdmUserDTO(UserDO userDO) {
        TyplmLoggerUtil.debug(log, () -> {
            return "convertPdmUserDTO 方法入参userDO ==> 【{}】";
        }, () -> {
            return new Object[]{JSONObject.toJSONString(userDO)};
        });
        PdmUserDTO pdmUserDTO = new PdmUserDTO();
        BeanUtils.copyProperties(userDO, pdmUserDTO);
        pdmUserDTO.setOid(userDO.getOid().toString());
        pdmUserDTO.setOtype(userDO.getOtype());
        pdmUserDTO.setAccount(userDO.getName());
        pdmUserDTO.setUsername(userDO.getFullname());
        TyplmLoggerUtil.debug(log, () -> {
            return "convertPdmUserDTO 返回值pdmUserDTO ==> 【{}】";
        }, () -> {
            return new Object[]{JSONObject.toJSONString(pdmUserDTO)};
        });
        return pdmUserDTO;
    }

    /**
     * 获取流程中每个任务节点详细信息，并设置节点参与者
     *
     * @return
     */
    public @NotNull List<UserTaskDTO> getUserTaskDTOS(WorkFlow workFlow, List<PdmUserDTO> userList,
                                                      BigInteger containerOid, String containerOtype) {
        List<UserTaskDTO> userTaskList = typlmWorkFlowContainerService.getAllUserTask(workFlow.getOid(),
                                                                                      containerOid,
                                                                                      containerOtype);
        //遍历设置流程节点的参与者
        if (CollUtil.isNotEmpty(userList)) {
            UserTaskDTO userTaskDTO = userTaskList.get(0);
            userTaskDTO.setUserList(userList);
        }
        return userTaskList;
    }

    @Override
    public void workIsPlan(BigInteger finalWorkFlowContainerId, String nodeIds) {
        WorkFlowContainerView workFlowContainerView = typlmWorkFlowContainerService
                .getWorkFlowContainerDetailByPrimaryKey(
                        finalWorkFlowContainerId);
        List<IdentifierEntity> flowList = new ArrayList<>();
        if ((workFlowContainerView instanceof WorkFlowObjectPackage)) {
            log.info("当前流程属于普通流程----》需求状态表是否排程");
            WorkFlowObjectPackage workFlowObjectPackage = (WorkFlowObjectPackage) workFlowContainerView;
            List<FlowObject> flowObjectList = workFlowObjectPackage.getFlowObjectList();
            if (CollUtil.isNotEmpty(flowObjectList)) {
                flowList = flowObjectList.stream().map(
                        m -> new IdentifierEntity(m.getRefObjectOid(), m.getRefObjectOtype())).distinct().collect(
                        Collectors.toList());
                BigInteger oid = flowList.get(0).getOid();
                /*
                 * 是否排程判断逻辑
                 *   1.根据oid查询需求排程表信息
                 *   2.根据排程表信息查询是否已经设置过 配置、组动单包、无需动力、包装组？、贴花组？、检小批
                 *   3.根据这些状态控制后续审批节点是否跳过
                 * */
                RtCfgStatusDTO rtCfgStatusDTO = new RtCfgStatusDTO();
                rtCfgStatusDTO.setOid(String.valueOf(oid));
                RtCfgStatusInfoDO rtCfgStatusInfoDO = rtCfgStatusInfoMapper.selectByStatusCode(rtCfgStatusDTO);

                DspfDemandDevplanDO dspfDemandDevplanDO = dspfDemandDevplanMapper
                        .selectDspfDemandDevplanByStatusId(rtCfgStatusInfoDO.getStatusid());

                Integer isAllocate = dspfDemandDevplanDO.getIsAllocate();
                if (isAllocate == 0) {
                    throw RTErrorCodeEnum.STATUS_INFO_CONTENT_IS_NULL.getException("请先进行分配");
                }

                // 清空节点执行人
                List<UserTaskDTO> userTaskList = workFlowContainerView.getUserTaskList();
                Map<String, UserTaskDTO> userTaskMap = userTaskList.stream()
                        .collect(Collectors.toMap(UserTaskDTO::getId, item -> item));

                List<UserTaskDTO> listUserNode = new ArrayList<>();
                if (StrUtil.isNotEmpty(nodeIds)) {
                    List<String> list = Arrays.asList(nodeIds.split(","));
                    list.stream().forEach(i -> {
                        UserTaskDTO userTaskDTO = userTaskMap.get(i);
                        listUserNode.add(userTaskDTO);
                        userTaskDTO.getUserList().clear();
                        log.info("角色分支判断：清空节点 {} 的执行人", i);
                    });
                }

                //如果排程设置了节点就将这个节点的人员设置到这个节点里面去 todo 目前只判断了贴花节点后续再改
                if (StrUtil.isNotEmpty(dspfDemandDevplanDO.getAppliqueBuild())) {
                    userTaskList.addAll(listUserNode);
                }
                workFlowContainerView.setUserTaskList(userTaskList);
                // 更新用户任务列表
                this.typlmFlowTaskUserService.updateUserTaskList(workFlowContainerView);

            }
        }
    }

    @Override
    public void setLeader(BigInteger finalWorkFlowContainerId, String condition, String nodes) {
        WorkFlowContainerView workFlowContainerView = typlmWorkFlowContainerService
                .getWorkFlowContainerDetailByPrimaryKey(
                        finalWorkFlowContainerId);
        try {
            List<UserTaskDTO> userTaskList = workFlowContainerView.getUserTaskList();
            Map<String, UserTaskDTO> userTaskMap = userTaskList.stream().collect(
                    Collectors.toMap(UserTaskDTO::getId, item -> item));
            String[] split = nodes.split(",");
            for (String node : split) {
                if (userTaskMap.containsKey(node)) {
                    UserTaskDTO userTaskDTO = userTaskMap.get(node);
                    userTaskDTO.getUserList().clear();
                }
            }
            typlmFlowTaskUserService.updateUserTaskList(workFlowContainerView);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("设置部门主管失败: {}", e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void workFlowCpmfb(BigInteger finalWorkFlowContainerId) {
        WorkFlowContainerView workFlowContainerView = typlmWorkFlowContainerService
                .getWorkFlowContainerDetailByPrimaryKey(
                        finalWorkFlowContainerId);
        List<IdentifierEntity> flowList = new ArrayList<>();
        if ((workFlowContainerView instanceof WorkFlowObjectPackage)) {
            log.info("当前流程属于普通流程----》BOM生成");
            WorkFlowObjectPackage workFlowObjectPackage = (WorkFlowObjectPackage) workFlowContainerView;
            List<FlowObject> flowObjectList = workFlowObjectPackage.getFlowObjectList();
            if (CollUtil.isNotEmpty(flowObjectList)) {
                flowList = flowObjectList.stream().map(
                        m -> new IdentifierEntity(m.getRefObjectOid(), m.getRefObjectOtype())).distinct().collect(
                        Collectors.toList());
                BigInteger oid = flowList.get(0).getOid();
                RtCfgStatusDTO rtCfgStatusDTO = new RtCfgStatusDTO();
                rtCfgStatusDTO.setOid(String.valueOf(oid));
                RtCfgStatusInfoDO rtCfgStatusInfoDO = rtCfgStatusInfoMapper.selectByStatusCode(rtCfgStatusDTO);
                List<DspfMbomBomDO> dspfMbomBomDOS = dspfMbomBomMapper.selectDspfMbomBomByStatusId(
                        rtCfgStatusInfoDO.getStatusid(), null);
                List<String> bomIds = dspfMbomBomDOS.stream()
                        .map(DspfMbomBomDO::getBomid)
                        .filter(Objects::nonNull)  // 过滤掉 null 值
                        .collect(Collectors.toList());
                List<DspfMbomDetailDO> mbomDetailList = dspfMbomDetailMapper.selectDspfMbomDetailListByBomids(bomIds);

                /*
                 * BOM生成逻辑
                 *   1.校验图纸正确性，出图是否正确
                 *   1.成品码生命周期状态置为已发布
                 *   2.构建成品BOM与转视图 已取消此逻辑
                 *   3.发布完成之后更新需求状态表、bom详情表成品码字段
                 *   4.需生成底层成品码对象，且将属性反写上去
                 * */

                StringBuffer stringBuffer = new StringBuffer();
                //校验图纸正确性，出图是否正确 todo** 暂时注释掉，这个卡控需要做成警告的方式
                //                this.bomDrawingVerify(mbomDetailList,stringBuffer);
                if (StrUtil.isNotEmpty(stringBuffer.toString())) {
                    throw RTErrorCodeEnum.STATUS_INFO_CONTENT_IS_NULL.getException(stringBuffer.toString());
                }

                // 使用编程式事务控制父级搭建
                DefaultTransactionDefinition def = new DefaultTransactionDefinition();
                def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
                TransactionStatus status = transactionManager.getTransaction(def);
                String productCodeDL = "";
                String productCodeZD = "";
                String productCodeCD = "";
                try {
                    // 根据otype字段分组
                    Map<String, List<DspfMbomDetailDO>> groupedByOtype = mbomDetailList.stream()
                            .filter(item -> item.getOtype() != null && item.getOtype() != "")  // 过滤掉 otype 为 null 的记录
                            .collect(Collectors.groupingBy(DspfMbomDetailDO::getOtype));

                    for (Map.Entry<String, List<DspfMbomDetailDO>> entry : groupedByOtype.entrySet()) {
                        String otype = entry.getKey();
                        List<DspfMbomDetailDO> detailList = entry.getValue();
                        if ("0".equals(otype)) {//动力BOM搭建
                            productCodeDL = this.creatProductCodeRules(rtCfgStatusInfoDO);
                            rtCfgBomService.buildBOM(detailList, productCodeDL, rtCfgStatusInfoDO);
                        }

                        if ("2".equals(otype)) {//传动BOM搭建
                            productCodeCD = this.creatProductCodeRules(rtCfgStatusInfoDO);
                            rtCfgBomService.buildBOM(detailList, productCodeCD, rtCfgStatusInfoDO);
                        }

                        if ("1".equals(otype)) {//终端BOM搭建
                            productCodeZD = this.creatProductCodeRules(rtCfgStatusInfoDO);
                            rtCfgBomService.buildBOM(detailList, productCodeZD, rtCfgStatusInfoDO);
                        }
                        rtCfgStatusInfoMapper.updateProductCodeByStatusid(productCodeZD, productCodeDL, productCodeCD,
                                                                          rtCfgStatusInfoDO.getStatusid());
                    }

                    // 手动提交事务，确保数据写入数据库
                    transactionManager.commit(status);
                } catch (Exception e) {
                    transactionManager.rollback(status);
                    throw e;
                }
                //todo 将动力、传动成品BOM结构搭建到终端成品BOM下面
                this.buildTreeProductCode(productCodeZD, productCodeDL, productCodeCD);

                //todo 需要优化删除
                //                List<DspfMbomBomDO> filteredList = dspfMbomBomDOS.stream()
                //                        .filter(item -> "1".equals(item.getOtype()))
                //                        .collect(Collectors.toList());
                //                if(IterUtil.isNotEmpty(filteredList)){
                //                    this.typlmBomOrdering(filteredList.get(0),dspfMbomBomDOS);
                //                }

            }

        }
    }

    /**
     * 成品码生成规则
     *
     * @param rtCfgStatusInfoDO
     * @return
     */
    private String creatProductCodeRules(RtCfgStatusInfoDO rtCfgStatusInfoDO) {
        //固定字母R+用途+开发令+认证+7位纯数字流水
        StringBuffer stringBuffer = new StringBuffer("R");
        //查询用途
        String usageCode = ratoCpytMapper.selectUsageCodeByName(rtCfgStatusInfoDO.getProductusage());
        if (StrUtil.isEmpty(usageCode)) {
            throw RTErrorCodeEnum.STATUS_INFO_CONTENT_IS_NULL
                    .getException("需求状态表【" + rtCfgStatusInfoDO.getStatuscode() + "】无产品用途信息");
        }
        String usageCodetrim = usageCode.trim();
        stringBuffer.append(String.format("%2s", usageCodetrim).replace(' ', '0'));

        //开发令
        String devcode = rtCfgStatusInfoDO.getDevcode().trim();
        stringBuffer.append(String.format("%4s", devcode).replace(' ', '0'));

        //认证
        String rzvalue = rtCfgStatusInfoMapper.selectRzByInfoid(rtCfgStatusInfoDO.getStatusid());
        if (StrUtil.isEmpty(rzvalue)) {
            throw RTErrorCodeEnum.STATUS_INFO_CONTENT_IS_NULL
                    .getException("需求状态表【" + rtCfgStatusInfoDO.getStatuscode() + "】无认证信息");
        }
        RtCertCombCertDO rtCertCombCert = new RtCertCombCertDO();
        rtCertCombCert.setCertname(rzvalue);
        List<RtCertCombCertDO> rtCertCombCertDOS = rtCertCombCertService.selectRtCertCombCertList(rtCertCombCert);
        if (IterUtil.isEmpty(rtCertCombCertDOS)) {
            throw RTErrorCodeEnum.STATUS_INFO_CONTENT_IS_NULL
                    .getException("需求状态表【" + rtCfgStatusInfoDO.getStatuscode() + "】的认证信息" + rzvalue + "无认证代号");
        }
        String rz = rtCertCombCertDOS.get(0).getCertcode().trim();
        stringBuffer.append(String.format("%3s", rz).replace(' ', '0'));
        stringBuffer.append("-");
        String serialNumber = iRtCfgSerialNumberService.getSerialNumber(stringBuffer.toString(), 7);

        return serialNumber;
    }

    private void buildTreeProductCode(String productCodeZD, String productCodeDL, String productCodeCD) {
        PartDO partDOZD = typlmPdmPartService.queryLastPartDoByPartNumber(productCodeZD);
        PartDO partDODL = typlmPdmPartService.queryLastPartDoByPartNumber(productCodeDL);
        PartDO partDOCD = typlmPdmPartService.queryLastPartDoByPartNumber(productCodeCD);


        PartBomView partBomView = new PartBomView();
        PartBomTreeNode parent = new PartBomTreeNode();
        parent.setOid(partDOZD.getOid());
        parent.setOtype(TableTypeConstrant.TY_PART_OTYPE);
        parent.setViewID(partDOZD.getViewdefoid());
        partBomView.setParent(parent);
        List<PartBomTreeNode> bomTreeNodeList = new ArrayList<>();

        PartBomTreeNode partBomTreeNode1 = new PartBomTreeNode();
        partBomTreeNode1.setViewName(RTPlmConstant.VIEW_DESIGN);
        partBomTreeNode1.setPartoid(String.valueOf(partDODL.getOid()));
        partBomTreeNode1.setPartotype(TableTypeConstrant.TY_PART_OTYPE);
        partBomTreeNode1.setAmount(1d);
        partBomTreeNode1.setMasterpartnumber(productCodeDL);
        partBomTreeNode1.setParentPartNumber(productCodeZD);
        partBomTreeNode1.setValue(10L);
        partBomTreeNode1.setAction("add");
        bomTreeNodeList.add(partBomTreeNode1);

        //        PartBomTreeNode partBomTreeNode2 = new PartBomTreeNode();
        //        partBomTreeNode2.setViewName(RTPlmConstant.VIEW_DESIGN);
        //        partBomTreeNode2.setPartoid(String.valueOf(partDOCD.getOid()));
        //        partBomTreeNode2.setPartotype(TableTypeConstrant.TY_PART_OTYPE);
        //        partBomTreeNode2.setAmount(1d);
        //        partBomTreeNode2.setMasterpartnumber(productCodeCD);
        //        partBomTreeNode2.setParentPartNumber(productCodeZD);
        //        partBomTreeNode2.setValue(20L);
        //        partBomTreeNode2.setAction("add");
        //        bomTreeNodeList.add(partBomTreeNode2);
        partBomView.setBomTreeNodeList(bomTreeNodeList);
        typlmPartBomAdapter.saveBomViewImmediately(partBomView);

    }

    private void batchAddPartUsageLink(ImportBOMItemDTO parentPart, ViewDefDO view,
                                       List<SaveObjIBADTO> objWithIbaList) {
        typlmPartUsageLinkService.batchDeletePartUsageLink(
                rtPartMapper.batchQueryPartUsageLinkDOByPartOid(Collections.singletonList(parentPart.getOid())));
        List<ImportBOMItemDTO> childLines = parentPart.getChildren();
        if (CollUtil.isNotEmpty(childLines)) {
            PartBomView partBomView = new PartBomView();
            PartBomTreeNode parent = new PartBomTreeNode();
            parent.setOid(parentPart.getOid());
            parent.setOtype(TableTypeConstrant.TY_PART_OTYPE);
            parent.setViewID(view.getOid());
            partBomView.setParent(parent);
            List<PartBomTreeNode> bomTreeNodeList = IntStream.range(0, childLines.size())
                    .mapToObj(i -> {
                        ImportBOMItemDTO partChildBomDTO = childLines.get(i);
                        String childNumber = partChildBomDTO.getCode();
                        String quantity = partChildBomDTO.getCount();
                        long quenceNo = (i + 1) * 10L;
                        partChildBomDTO.setQuenceNo(quenceNo);
                        PartBomTreeNode partBomTreeNode = new PartBomTreeNode();
                        partBomTreeNode.setViewName("Design");
                        partBomTreeNode.setPartoid(String.valueOf(partChildBomDTO.getOid()));
                        partBomTreeNode.setPartotype(TableTypeConstrant.TY_PART_OTYPE);
                        try {
                            double amountD = Double.parseDouble(quantity);
                            partBomTreeNode.setAmount(amountD);
                        } catch (Exception e) {
                            partBomTreeNode.setAmount(1d);
                        }
                        partBomTreeNode.setMasterpartnumber(childNumber);
                        partBomTreeNode.setParentPartNumber(parentPart.getCode());
                        partBomTreeNode.setValue(quenceNo);
                        partBomTreeNode.setAction("add");
                        return partBomTreeNode;
                    })
                    .collect(Collectors.toList());
            partBomView.setBomTreeNodeList(bomTreeNodeList);
            Map<BigInteger, Long> map = typlmPartBomAdapter.saveBomViewImmediately(partBomView);
            // 将 map 的 key 赋值到 usageLinkOid
            Map<Long, BigInteger> reversedMap = map.entrySet().stream()
                    .collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey));
            for (ImportBOMItemDTO dto : childLines) {
                Long quenceNo = dto.getQuenceNo();
                if (quenceNo != null && reversedMap.containsKey(quenceNo)) {
                    BigInteger usageLinkOid = reversedMap.get(quenceNo);
                    dto.setUsageLinkOid(usageLinkOid);
                }
            }

            buildSaveIbaDTO(parentPart, objWithIbaList);


            for (ImportBOMItemDTO child : childLines) {
                batchAddPartUsageLink(child, view, objWithIbaList);
            }
        }
    }

    public void buildSaveIbaDTO(ImportBOMItemDTO importPartBomDTO, List<SaveObjIBADTO> objWithIbaList) {

        List<ImportBOMItemDTO> childLines = importPartBomDTO.getChildren();
        for (ImportBOMItemDTO partChildBomDTO : childLines) {
            List<IbaDTO> objIbaList = new ArrayList<>();
            IbaDTO ibaDTO1 = new IbaDTO();
            ibaDTO1.setKey("SegmNum");
            ibaDTO1.setValue(partChildBomDTO.getSegment());
            objIbaList.add(ibaDTO1);
            IbaDTO ibaDTO2 = new IbaDTO();
            ibaDTO2.setKey("ManufacturingAttr");
            ibaDTO2.setValue(partChildBomDTO.getManufacturing());
            objIbaList.add(ibaDTO2);
            IbaDTO ibaDTO3 = new IbaDTO();
            ibaDTO3.setKey("Position");
            ibaDTO3.setValue(partChildBomDTO.getLocation());
            objIbaList.add(ibaDTO3);
            if (CollUtil.isNotEmpty(objIbaList)) {
                SaveObjIBADTO saveObjIBADTO = new SaveObjIBADTO();
                CTyEntityBaseDO ctyEntityBaseDO = new CTyEntityBaseDO();
                ctyEntityBaseDO.setOid(partChildBomDTO.getUsageLinkOid());
                ctyEntityBaseDO.setOtype(TableTypeConstrant.TY_PARTUSAGELINK_OTYPE);
                saveObjIBADTO.setCTyEntityBaseDO(ctyEntityBaseDO);
                saveObjIBADTO.setObjIbaList(objIbaList);
                objWithIbaList.add(saveObjIBADTO);
            }
        }
    }


    private TyplmFolderObjDTO tyQueryCode(DspfMbomBomDO dspfMbomBomDO) {
        String jsonQueryCode = "{\"subFolderOid\":\"715670121054076928\",\"subFolderOtype\":\"ty.inteplm.folder.CTySubFolder\",\"curPage\":1,\"pageSize\":20,\"needCount\":false,\"keyword\":\"RV145MS00W0Q-0JS01\",\"subFolderFilterDTO\":{\"oid\":\"363292770112602112\",\"otype\":\"ty.inteplm.folder.CTyTableViewDescriptor\",\"name\":\"全部\",\"createstamp\":\"2022-11-21 23:21:09\",\"updatestamp\":\"2024-05-08 16:07:41\",\"modifystamp\":\"2024-05-08 16:07:41\",\"updatecount\":\"2\",\"markfordelete\":\"0\",\"identifierRef\":{\"oid\":\"363292770112602112\",\"otype\":\"ty.inteplm.folder.CTyTableViewDescriptor\"},\"containeroid\":\"251680307611926528\",\"containerotype\":\"ty.inteplm.product.CTyPDMLinkProduct\",\"attributes\":\"All\",\"tableid\":\"folderbrowser_PDM\",\"system\":\"1\",\"published\":\"1\",\"owneroid\":\"105\",\"ownerotype\":\"ty.inteplm.org.CTyUser\",\"matchall\":\"1\",\"inheriteddomain\":\"0\",\"hidden\":\"0\",\"frozencolumns\":\"-1\",\"domainoid\":\"251680307620315136\",\"domainotype\":\"ty.inteplm.domain.CTyDomain\",\"viewgroup\":\"folder\",\"systemdefault\":1,\"searchCondition\":{\"typeList\":[],\"conditionJoint\":\"and\",\"conditionGroups\":[],\"pageNum\":1,\"pageSize\":20,\"needIBA\":false,\"columns\":[{\"propertyName\":\"changestatus\",\"displayName\":\"更改状况\",\"masterProperty\":false,\"fixed\":\"\",\"width\":\"50\",\"sortable\":false,\"fieldList\":[],\"virtual\":false,\"foreignColumnMaster\":false,\"canNotRemove\":false,\"enum\":false},{\"propertyName\":\"graphical\",\"displayName\":\"图形标识\",\"masterProperty\":false,\"fixed\":\"\",\"width\":\"50\",\"sortable\":false,\"fieldList\":[],\"virtual\":false,\"foreignColumnMaster\":false,\"canNotRemove\":false,\"enum\":false},{\"propertyName\":\"thumbnailFile\",\"displayName\":\"缩略图\",\"masterProperty\":false,\"fixed\":\"\",\"width\":\"120\",\"sortable\":false,\"fieldList\":[],\"virtual\":false,\"foreignColumnMaster\":false,\"canNotRemove\":false,\"enum\":false},{\"propertyName\":\"identifier\",\"displayName\":\"标识\",\"masterProperty\":false,\"fixed\":\"\",\"width\":\"300\",\"sortable\":false,\"fieldList\":[],\"virtual\":false,\"foreignColumnMaster\":false,\"canNotRemove\":false,\"enum\":false},{\"propertyName\":\"state\",\"displayName\":\"生命周期状态\",\"masterProperty\":false,\"fixed\":\"\",\"width\":\"80\",\"sortable\":false,\"fieldList\":[],\"virtual\":false,\"foreignColumnMaster\":false,\"canNotRemove\":false,\"enum\":false},{\"propertyName\":\"typeDefName\",\"displayName\":\"类型\",\"masterProperty\":false,\"fixed\":\"\",\"width\":\"80\",\"sortable\":false,\"fieldList\":[],\"virtual\":false,\"foreignColumnMaster\":false,\"canNotRemove\":false,\"enum\":false},{\"propertyName\":\"modifier\",\"displayName\":\"修改者\",\"masterProperty\":false,\"fixed\":\"\",\"width\":\"80\",\"sortable\":false,\"fieldList\":[],\"virtual\":false,\"foreignColumnMaster\":false,\"canNotRemove\":false,\"enum\":false},{\"propertyName\":\"modifystamp\",\"displayName\":\"修改时间\",\"masterProperty\":false,\"fixed\":\"\",\"width\":\"80\",\"sortable\":false,\"fieldList\":[],\"virtual\":false,\"foreignColumnMaster\":false,\"canNotRemove\":false,\"enum\":false}],\"needThumbnailFile\":false,\"searchType\":1},\"searchColumnList\":[{\"propertyName\":\"changestatus\",\"displayName\":\"更改状况\",\"masterProperty\":false,\"fixed\":\"\",\"width\":\"50\",\"sortable\":false,\"fieldList\":[],\"virtual\":false,\"foreignColumnMaster\":false,\"canNotRemove\":false,\"enum\":false},{\"propertyName\":\"graphical\",\"displayName\":\"图形标识\",\"masterProperty\":false,\"fixed\":\"\",\"width\":\"50\",\"sortable\":false,\"fieldList\":[],\"virtual\":false,\"foreignColumnMaster\":false,\"canNotRemove\":false,\"enum\":false},{\"propertyName\":\"thumbnailFile\",\"displayName\":\"缩略图\",\"masterProperty\":false,\"fixed\":\"\",\"width\":\"120\",\"sortable\":false,\"fieldList\":[],\"virtual\":false,\"foreignColumnMaster\":false,\"canNotRemove\":false,\"enum\":false},{\"propertyName\":\"identifier\",\"displayName\":\"标识\",\"masterProperty\":false,\"fixed\":\"\",\"width\":\"300\",\"sortable\":false,\"fieldList\":[],\"virtual\":false,\"foreignColumnMaster\":false,\"canNotRemove\":false,\"enum\":false},{\"propertyName\":\"state\",\"displayName\":\"生命周期状态\",\"masterProperty\":false,\"fixed\":\"\",\"width\":\"80\",\"sortable\":false,\"fieldList\":[],\"virtual\":false,\"foreignColumnMaster\":false,\"canNotRemove\":false,\"enum\":false},{\"propertyName\":\"typeDefName\",\"displayName\":\"类型\",\"masterProperty\":false,\"fixed\":\"\",\"width\":\"80\",\"sortable\":false,\"fieldList\":[],\"virtual\":false,\"foreignColumnMaster\":false,\"canNotRemove\":false,\"enum\":false},{\"propertyName\":\"modifier\",\"displayName\":\"修改者\",\"masterProperty\":false,\"fixed\":\"\",\"width\":\"80\",\"sortable\":false,\"fieldList\":[],\"virtual\":false,\"foreignColumnMaster\":false,\"canNotRemove\":false,\"enum\":false},{\"propertyName\":\"modifystamp\",\"displayName\":\"修改时间\",\"masterProperty\":false,\"fixed\":\"\",\"width\":\"80\",\"sortable\":false,\"fieldList\":[],\"virtual\":false,\"foreignColumnMaster\":false,\"canNotRemove\":false,\"enum\":false}],\"info\":{\"classDisplay\":\"\",\"typeDisplay\":\"所有类型\",\"contextDisplay\":\"所有上下文\",\"conditionDisplayList\":[],\"columnDisplay\":\"更改状况、图形标识、缩略图、标识、生命周期状态、类型、修改者、修改时间\"},\"createSystemView\":false,\"needReturnOptionColumn\":false,\"clazzDisplayName\":\"\",\"displayFullName\":\"全部\"}}";
        TySubFolderFilterQuery tySubFolderFilterQuery = JSONUtil.toBean(jsonQueryCode, TySubFolderFilterQuery.class);
        tySubFolderFilterQuery.setKeyword(dspfMbomBomDO.getMbomcode());
        PageInfo<TyplmFolderObjDTO> folderObjectByFilter = typlmSubFilterObjectService.getFolderObjectByFilter(
                tySubFolderFilterQuery);
        List<TyplmFolderObjDTO> typlmFolderObjDTOS = folderObjectByFilter.getList();
        if (IterUtil.isEmpty(typlmFolderObjDTOS)) {
            throw RTErrorCodeEnum.STATUS_INFO_CONTENT_IS_NULL.getException(
                    "未查询到【" + dspfMbomBomDO.getMbomcode() + "】数据");
        }
        List<TyplmFolderObjDTO> filteredList = typlmFolderObjDTOS.stream()
                .filter(objDTO -> dspfMbomBomDO.getMbomcode().equals(objDTO.getObjectNumber()))
                .collect(Collectors.toList());
        if (IterUtil.isEmpty(filteredList)) {
            throw RTErrorCodeEnum.STATUS_INFO_CONTENT_IS_NULL.getException(
                    "未查询到【" + dspfMbomBomDO.getMbomcode() + "】数据");
        }
        TyplmFolderObjDTO typlmFolderObjDTO = filteredList.get(0);
        return typlmFolderObjDTO;
    }

    private void typlmCodeOut(DspfMbomBomDO dspfMbomBomDO, TyplmFolderObjDTO typlmFolderObjDTO) {
        CommonIteratorVO commonIteratorVO = new CommonIteratorVO();
        commonIteratorVO.setId(String.valueOf(typlmFolderObjDTO.getOid()));
        commonIteratorVO.setTypeDefName(typlmFolderObjDTO.getCadType());
        com.ty.basic.response.ResponseResult<List<BusinessObjectVO>> listResponseResult = typlmIterationController
                .batchCheckOut(
                        Arrays.asList(commonIteratorVO));
        if (!"SUCCESS".equals(listResponseResult.getResult())) {
            throw RTErrorCodeEnum.STATUS_INFO_CONTENT_IS_NULL.getException("【" + dspfMbomBomDO + "】检出失败");
        }
    }

    private void typlmCodeIn(DspfMbomBomDO dspfMbomBomDO, TyplmFolderObjDTO typlmFolderObjDTO) {
        CommonIteratorVO commonIteratorVO = new CommonIteratorVO();
        commonIteratorVO.setId(String.valueOf(typlmFolderObjDTO.getOid()));
        commonIteratorVO.setTypeDefName(typlmFolderObjDTO.getCadType());
        com.ty.basic.response.ResponseResult<List<BusinessObjectVO>> listResponseResult = typlmIterationController
                .batchCheckIn(
                        Arrays.asList(commonIteratorVO));
        if (!"SUCCESS".equals(listResponseResult.getResult())) {
            throw RTErrorCodeEnum.STATUS_INFO_CONTENT_IS_NULL.getException("【" + dspfMbomBomDO + "】检入失败");
        }

    }

    private void bomAddBatchCheckV2(String materialcode, Map<String, Object> map) {
        String jsonBomAddBatchCheck = "{\"bomAddBatchCheckParentDTOList\":[{\"parentNumber\":\"part202509061358042964939\",\"parentMasterId\":\"734101118771773440\",\"parentViewName\":\"Design\",\"childList\":[{\"number\":\"18100-Z360110-0001\",\"masterId\":\"728682524089974784\",\"viewName\":\"Design\"}]}],\"isCheckView\":true,\"isCheckCircularReference\":true}";
        cn.hutool.json.JSONObject jsonObject = JSONUtil.parseObj(jsonBomAddBatchCheck);

        // 获取bomAddBatchCheckParentDTOList数组
        cn.hutool.json.JSONArray parentList = jsonObject.getJSONArray("bomAddBatchCheckParentDTOList");
        // 遍历父对象列表
        for (Object parentObj : parentList) {
            cn.hutool.json.JSONObject parent = JSONUtil.parseObj(parentObj);

            // 修改父对象的相关字段
            parent.set("parentNumber", map.get("PARENTNUMBER").toString());
            parent.set("parentMasterId", map.get("PARENTMASTERID").toString());
            parent.set("parentViewName", "Design");

            // 获取子对象列表
            JSONArray childList = parent.getJSONArray("childList");

            // 遍历子对象列表
            for (Object childObj : childList) {
                cn.hutool.json.JSONObject child = JSONUtil.parseObj(childObj);
                // 修改子对象的相关字段
                child.set("number", materialcode);
                String masterId = rtCfgBomMapper.selectMasterIdByNumber(materialcode);
                child.set("masterId", masterId);
                child.set("viewName", "Design");
            }
        }
        BomAddBatchCheckDTO bomAddBatchCheckDTO = JSONUtil.toBean(jsonObject.toStringPretty(),
                                                                  BomAddBatchCheckDTO.class);
        com.ty.basic.response.ResponseResult<Boolean> booleanResponseResult = typlmBomController.bomAddBatchCheck(
                bomAddBatchCheckDTO);
        if (!booleanResponseResult.getData()) {
            throw RTErrorCodeEnum.STATUS_INFO_CONTENT_IS_NULL.getException(
                    "成品BOM搭建子集物料数据异常【/rest/v1/bom/bomAddBatchCheck接口】");
        }
    }

    private void saveBomViewListImmediatelyV2(String materialcode, String materialname, TyplmFolderObjDTO partInfoVO,
                                              Map<String, Object> map) {
        String jsonSaveBomViewListImmediately = "[{\"parent\":{\"oid\":\"734112810650025984\",\"otype\":\"ty.inteplm.part.CTyPart\",\"name\":\"名称1\",\"viewID\":\"323899843229581312\"},\"bomTreeNodeList\":[{\"oid\":\"\",\"partoid\":\"733666789905383424\",\"partotype\":\"ty.inteplm.part.CTyPart\",\"objOid\":\"733666789905383424\",\"objOtype\":\"ty.inteplm.part.CTyPart\",\"oriAreference\":\"\",\"oriAmount\":\"1\",\"amount\":\"1\",\"masterpartnumber\":\"18100-Z310110-0001\",\"mastername\":\"衍生物料码1\",\"parentPartNumber\":\"part202509061358042964939\",\"parentPartName\":\"名称1\",\"version\":\"A\",\"lifecyclestagekey\":\"Creating\",\"iterationid\":\"2\",\"value\":20,\"action\":\"add\",\"viewName\":\"Design\"}],\"addBOMFlag\":true}]";
        JSONArray jsonArray = JSONUtil.parseArray(jsonSaveBomViewListImmediately);

        // 遍历数组中的每个对象
        for (int i = 0; i < jsonArray.size(); i++) {
            Object obj = jsonArray.get(i);
            cn.hutool.json.JSONObject jsonObjectVi = JSONUtil.parseObj(obj);

            try {
                // 获取parent对象
                cn.hutool.json.JSONObject parent = jsonObjectVi.getJSONObject("parent");
                if (parent == null) {
                    parent = JSONUtil.createObj();
                    jsonObjectVi.set("parent", parent);
                }

                // 替换parent对象中的所有值
                parent.set("oid", partInfoVO.getOid().toString());
                parent.set("otype", map.get("OTYPE"));
                parent.set("name", map.get("NAME"));
                parent.set("viewID", map.get("VIEWID").toString());

                // 获取bomTreeNodeList数组
                JSONArray bomList = jsonObjectVi.getJSONArray("bomTreeNodeList");
                if (bomList == null) {
                    bomList = JSONUtil.createArray();
                    jsonObjectVi.set("bomTreeNodeList", bomList);
                }

                // 遍历bomTreeNodeList中的每个对象
                for (int j = 0; j < bomList.size(); j++) {
                    Object bomObj = bomList.get(j);
                    cn.hutool.json.JSONObject bomNode = JSONUtil.parseObj(bomObj);

                    // 替换指定字段值
                    Map<String, Object> mapBOMNode = rtCfgBomMapper.selectParentByBomOidIn(materialcode);
                    String oid = rtCfgBomMapper.selectOidByNumberOut(materialcode);
                    if (StrUtil.isNotEmpty(oid)) {
                        throw RTErrorCodeEnum.STATUS_INFO_CONTENT_IS_NULL.getException(
                                "当前物料码【" + materialcode + "】为检出状态");
                    }
                    oid = rtCfgBomMapper.selectOidByNumberIn(materialcode);
                    bomNode.set("mastername", materialname);
                    bomNode.set("masterpartnumber", materialname);
                    bomNode.set("objOid", oid);
                    bomNode.set("objOtype", mapBOMNode.get("OTYPE"));
                    bomNode.set("parentPartName", map.get("NAME"));
                    bomNode.set("parentPartNumber", map.get("PARENTNUMBER"));
                    bomNode.set("partoid", oid);
                    bomNode.set("partotype", map.get("OTYPE"));

                    // 显式将修改后的对象放回数组
                    bomList.set(j, bomNode);
                }

                // 显式将修改后的对象放回数组
                jsonArray.set(i, jsonObjectVi);
            } catch (Exception e) {
                // 打印异常信息，便于排查问题
                e.printStackTrace();
            }
        }
        List<PartBomView> partBomViews = JSONUtil.toList(jsonArray, PartBomView.class);
        com.ty.basic.response.ResponseResult<Map<BigInteger, Long>> mapResponseResult = typlmBomController
                .saveBomViewListImmediately(
                        partBomViews);
        if (MapUtil.isEmpty(mapResponseResult.getData())) {
            throw RTErrorCodeEnum.STATUS_INFO_CONTENT_IS_NULL.getException(
                    "成品BOM搭建子集物料数据异常【/rest/v1/bom/saveBomViewListImmediately接口】");
        }

    }

    private void typlmBomOrdering(DspfMbomBomDO dspfMbomBomDO, List<DspfMbomBomDO> mbomBomDOList) {
        List<DspfMbomBomDO> filteredList = mbomBomDOList.stream()
                .filter(item -> "0".equals(item.getOtype()) || "2".equals(item.getOtype()))
                .collect(Collectors.toList());
        if (IterUtil.isNotEmpty(filteredList)) {
            //查询成品码数据
            TyplmFolderObjDTO typlmFolderObjDTO = this.tyQueryCode(dspfMbomBomDO);

            //检出
            this.typlmCodeOut(dspfMbomBomDO, typlmFolderObjDTO);

            //根据成品BOM编码查询出parentNumber、parentMasterId、parentViewName字段
            Map<String, Object> map = rtCfgBomMapper.selectParentByBomOidOut(dspfMbomBomDO.getMbomcode());
            if (MapUtil.isNotEmpty(map)) {
                throw RTErrorCodeEnum.STATUS_INFO_CONTENT_IS_NULL.getException(
                        "当前成品码【" + dspfMbomBomDO.getMbomcode() + "】已被检出");
            }
            map = rtCfgBomMapper.selectParentByBomOidIn(dspfMbomBomDO.getMbomcode());
            Map<String, Object> finalMap = map;
            filteredList.stream().forEach(i -> {
                //子级搭建
                this.bomAddBatchCheckV2(i.getMbomcode(), finalMap);
                this.saveBomViewListImmediatelyV2(i.getMbomcode(), i.getBomdescr(), typlmFolderObjDTO, finalMap);
            });

            //检入
            this.typlmCodeIn(dspfMbomBomDO, typlmFolderObjDTO);
        }


    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void workSendSapAndMom(BigInteger finalWorkFlowContainerId) {
        WorkFlowContainerView workFlowContainerView = typlmWorkFlowContainerService
                .getWorkFlowContainerDetailByPrimaryKey(
                        finalWorkFlowContainerId);
        List<IdentifierEntity> flowList = new ArrayList<>();
        if ((workFlowContainerView instanceof WorkFlowObjectPackage)) {
            log.info("当前流程属于普通流程----》下发sap，mom");
            WorkFlowObjectPackage workFlowObjectPackage = (WorkFlowObjectPackage) workFlowContainerView;
            List<FlowObject> flowObjectList = workFlowObjectPackage.getFlowObjectList();
            if (CollUtil.isNotEmpty(flowObjectList)) {
                flowList = flowObjectList.stream().map(
                        m -> new IdentifierEntity(m.getRefObjectOid(), m.getRefObjectOtype())).distinct().collect(
                        Collectors.toList());
                BigInteger oid = flowList.get(0).getOid();
                RtCfgStatusDTO rtCfgStatusDTO = new RtCfgStatusDTO();
                rtCfgStatusDTO.setOid(String.valueOf(oid));
                RtCfgStatusInfoDO rtCfgStatusInfoDO = rtCfgStatusInfoMapper.selectByStatusCode(rtCfgStatusDTO);
                //                List<RtCfgBomDO> list = rtCfgBomMapper.getRtCfgBuildBOMList(rtCfgStatusInfoDO.getStatusid(),null);
                StringBuffer stringBuffer = this.sendSapAndMom(rtCfgStatusInfoDO);
                //                if(StrUtil.isNotEmpty(stringBuffer.toString())){
                //                    throw RTErrorCodeEnum.STATUS_INFO_CONTENT_IS_NULL.getException(
                //                            "下发失败："+stringBuffer.toString());
                //                }
            }

        }
    }

    /**
     * 下发至sap,mom
     *
     * @param
     */
    private StringBuffer sendSapAndMom(RtCfgStatusInfoDO rtCfgStatusInfoDO) {

        //异常记录
        StringBuffer stringBuffer = new StringBuffer("");

        List<DspfMbomBomDO> dspfMbomBomDOS = dspfMbomBomMapper.selectDspfMbomBomByStatusId(
                rtCfgStatusInfoDO.getStatusid(), null);
        List<String> bomIds = dspfMbomBomDOS.stream()
                .map(DspfMbomBomDO::getBomid)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
        List<DspfMbomDetailDO> dspfMbomDetailDOS = dspfMbomDetailMapper.selectDspfMbomDetailListByBomids(bomIds);
        //下发sap
        if (IterUtil.isNotEmpty(dspfMbomDetailDOS)) {
            List<RestAdapterWlDTO.InData> item = new ArrayList<>();
            RestAdapterWlDTO restAdapterWlDTO = new RestAdapterWlDTO();
            RestAdapterWlDTO.InTab inTab = new RestAdapterWlDTO.InTab();

            List<RestAdapterBomDTO.InData> bomItem = new ArrayList<>();
            RestAdapterBomDTO restAdapterBomDTO = new RestAdapterBomDTO();
            RestAdapterBomDTO.InTab bomInTab = new RestAdapterBomDTO.InTab();

            dspfMbomDetailDOS.stream().forEach(i -> {
                //先查询此物料是否导入过sap，如果是导入过就不再下发sap todo 暂定 后面补全此逻辑现在只管下发出去

                //获取扩展属性里面的单位 和 是否出图
                PartDO partDO = typlmPdmPartService.queryLastPartDoByPartNumber(i.getMaterialcode());
                TyplmAttributeServiceImpl bean = SpringUtil.getBean(TyplmAttributeServiceImpl.class);
                Map<String, List<String>> ibaAttributeMap = bean.getIbaAttributeMap(partDO.getOid(), partDO.getOtype());

                RestAdapterWlDTO.InData inData = new RestAdapterWlDTO.InData(rtCfgStatusInfoDO, i, ibaAttributeMap);
                item.add(inData);

                RestAdapterBomDTO.InData bomInData = new RestAdapterBomDTO.InData(rtCfgStatusInfoDO, i,
                                                                                  ibaAttributeMap);
                bomItem.add(bomInData);
            });
            //物料主数据下发
            inTab.setItem(item);
            restAdapterWlDTO.setIN_TAB(inTab);
            RestAdapterWlDTO adapterWlDTO = sapApiService.restAdapterWl(restAdapterWlDTO);
            //根据返回结果修改bom表是否导入sap状态
            List<RestAdapterWlDTO.OutData> outItems = adapterWlDTO.getOUT_TAB().getItem();
            if (IterUtil.isNotEmpty(outItems)) {
                outItems.stream().forEach(i -> {
                    if ("S".equals(i.getMSGTY())) {
                        //todo 是否导入sap逻辑暂时先不写先保证能下发
                        //                        rtCfgBomMapper.updateIsImportSapByNumber(i.getMATNR());
                    }
                });

            }
            //todo 这里需要接口日志记录发送成功还是失败
            InterfaceLogRecordDO interfaceLogRecordDO =
                    new InterfaceLogRecordDO(
                            String.valueOf(snowflakeIdComponent.getInstance().nextId()),
                            IpAddressConstant.SAP_CS_WLDR, "物料主数据下发SAP", "PLM->SAP",
                            JSONUtil.toJsonStr(restAdapterWlDTO),
                            JSONUtil.toJsonStr(outItems),
                            TyAccountContext.getUser().getName(),
                            new Date()
                    );
            interfaceLogRecordMapper.insertInterfaceLogRecord(interfaceLogRecordDO);

            //BOM数据下发
            bomInTab.setItem(bomItem);
            restAdapterBomDTO.setIN_TAB(bomInTab);
            RestAdapterBomDTO bomDTO = sapApiService.restAdapterBom(restAdapterBomDTO);
            if (!"S".equals(bomDTO.getMSGTY())) {
                stringBuffer.append("下发SAP失败:" + bomDTO.getMSGTXT());
            }
            //todo 这里需要接口日志记录发送成功还是失败
            InterfaceLogRecordDO logRecordDO =
                    new InterfaceLogRecordDO(
                            String.valueOf(snowflakeIdComponent.getInstance().nextId()),
                            IpAddressConstant.SAP_CS_BOMDR, "物料BOM下发SAP", "PLM->SAP",
                            JSONUtil.toJsonStr(restAdapterBomDTO),
                            JSONUtil.toJsonStr(bomDTO),
                            TyAccountContext.getUser().getName(),
                            new Date()
                    );
            interfaceLogRecordMapper.insertInterfaceLogRecord(logRecordDO);

        } else {
            stringBuffer.append("下发SAP失败,没有物料数据");
        }

        //下发MOM
        if (ObjectUtil.isNotEmpty(rtCfgStatusInfoDO)) {
            String moduleid = rtCfgStatusInfoDO.getModuleid();
            List<MomValueDTO> momValueList = rtCfgStatusInfoMapper.selectModulesubByMid(moduleid);
            if (IterUtil.isNotEmpty(momValueList)) {
                Map<String, String> aggregatedMap = momValueList.stream()
                        .filter(dto -> dto.getMapperName() != null && dto.getSelectValueName() != null)
                        .collect(Collectors.groupingBy(
                                MomValueDTO::getMapperName,
                                Collectors.mapping(
                                        MomValueDTO::getSelectValueName,
                                        Collectors.joining(",")
                                )
                        ));
                RestAdapterMomDTO restAdapterMomDTO = new RestAdapterMomDTO(aggregatedMap);
                MomApiResponseVO momApiResponseVO = momApiService.restInvoke(restAdapterMomDTO);
                if (!"S".equals(momApiResponseVO.getStatus())) {
                    stringBuffer.append("下发MOM失败:" + momApiResponseVO.getMessage());
                }
                //todo 这里需要接口日志记录发送成功还是失败
                InterfaceLogRecordDO logRecordMOM =
                        new InterfaceLogRecordDO(
                                String.valueOf(snowflakeIdComponent.getInstance().nextId()),
                                IpAddressConstant.MOM_CS_ZTKZ_CQ, "物料BOM下发MOM", "PLM->MOM",
                                JSONUtil.toJsonStr(restAdapterMomDTO),
                                JSONUtil.toJsonStr(momApiResponseVO),
                                TyAccountContext.getUser().getName(),
                                new Date()
                        );
                interfaceLogRecordMapper.insertInterfaceLogRecord(logRecordMOM);

            } else {
                stringBuffer.append("下发MOM失败,需求状态表中无MOM所需要的数据");
            }
        }
        return stringBuffer;
    }

    private void bomDrawingVerify(List<DspfMbomDetailDO> list, StringBuffer stringBuffer) {
        /*
         * BOM校验逻辑如下
         *   1.检查物料图纸是否出图，出图是否正确
         * */
        if (IterUtil.isNotEmpty(list)) {
            list.stream().forEach(i -> {
                String partnumber = i.getMaterialcode();
                if (StrUtil.isEmpty(partnumber)) {
                    stringBuffer.append("BOM还未搭建完成，缺少物料码,");
                }
                //获取图号(字符串前13位)
                if (partnumber.length() >= 13) {
                    String drawingStr = partnumber.substring(0, 13);
                    //根据图号编码获取底层接口进行判断是否绑定的图纸正确
                    this.drawingVerify(drawingStr, stringBuffer);
                } else {
                    stringBuffer.append("BOM还未搭建完成，未搭建图号为【" + partnumber + "】,");
                }
            });
        }
    }

    /**
     * 根据图号编码获取底层接口进行判断是否绑定的图纸正确
     *
     * @param drawingStr
     */
    private void drawingVerify(String drawingStr, StringBuffer stringBuffer) {

        //todo 需要优化删除
        //        Map<String,String> mapOut = rtCfgBomMapper.selectAttributevalueByNumberOut(drawingStr);

        PartDO partDO = typlmPdmPartService.queryLastPartDoByPartNumber(drawingStr);
        String lifecycleState = partDO.getLifecyclestagekey();

        if (!"RELEASED".equals(lifecycleState)) {
            stringBuffer.append("此图号【" + drawingStr + "】不是已生效状态,");
        }

        Map<String, String> map = rtCfgBomMapper.selectAttributevalueByNumberIn(String.valueOf(partDO.getOid()),
                                                                                "输出要求");

        //todo 需要优化删除        map = rtCfgBomMapper.selectAttributevalueByNumberIn(drawingStr,"输出要求");
        if (MapUtil.isEmpty(map)) {
            stringBuffer.append("此图号未勾选输出要求【" + drawingStr + "】,");
        }
        String attributevalue = map.get("ATTRIBUTEVALUE");
        String partId = String.valueOf(map.get("OID"));
        //如果无需出图就不用判断图纸一致的逻辑
        Map<String, String> mapwxct = rtCfgBomMapper.selectAttributevalueByNumberIn(String.valueOf(partDO.getOid()),
                                                                                    "无需出图");
        if (MapUtil.isEmpty(mapwxct)) {
            List<DocDetails> docDetails = typlmPartRelObjectService.queryPartRelatedDocInfo(new BigInteger(partId));
            if (IterUtil.isNotEmpty(docDetails)) {
                String collect = docDetails.stream()
                        .map(DocDetails::getTypeDefName)  // 提取 typeDefName 字段
                        .filter(name -> name != null && !name.trim().isEmpty())  // 过滤空值
                        .collect(Collectors.joining(", "));// 用逗号拼接
                String descByCode = DrawingEnums.getDescByCode(attributevalue);
                if (!descByCode.contains(collect)) {
                    stringBuffer.append("此图号绑定图纸与输出结果不一致【" + drawingStr + "】,");
                }
            } else {
                stringBuffer.append("此图号未绑定图纸【" + drawingStr + "】,");
            }
        }

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void workBomVerify(BigInteger finalWorkFlowContainerId) {
        WorkFlowContainerView workFlowContainerView = typlmWorkFlowContainerService
                .getWorkFlowContainerDetailByPrimaryKey(
                        finalWorkFlowContainerId);
        List<IdentifierEntity> flowList = new ArrayList<>();
        if ((workFlowContainerView instanceof WorkFlowObjectPackage)) {
            log.info("当前流程属于普通流程----》成品BOM校验");
            WorkFlowObjectPackage workFlowObjectPackage = (WorkFlowObjectPackage) workFlowContainerView;
            List<FlowObject> flowObjectList = workFlowObjectPackage.getFlowObjectList();
            if (CollUtil.isNotEmpty(flowObjectList)) {
                flowList = flowObjectList.stream().map(
                        m -> new IdentifierEntity(m.getRefObjectOid(), m.getRefObjectOtype())).distinct().collect(
                        Collectors.toList());
                BigInteger oid = flowList.get(0).getOid();
                RtCfgStatusDTO rtCfgStatusDTO = new RtCfgStatusDTO();
                rtCfgStatusDTO.setOid(String.valueOf(oid));
                RtCfgStatusInfoDO rtCfgStatusInfoDO = rtCfgStatusInfoMapper.selectByStatusCode(rtCfgStatusDTO);
                //                List<RtCfgBomDO> list = rtCfgBomMapper.getRtCfgBuildBOMList(rtCfgStatusInfoDO.getStatusid(),null);

                //根据当前节点名称获取otype
                String otype = this.getOtypeByTaskName(workFlowObjectPackage.getFlowTaskRecordList());

                //异常汇总字符串
                StringBuffer stringBuffer = new StringBuffer("");

                List<DspfMbomBomDO> dspfMbomBomDOs = dspfMbomBomMapper.selectDspfMbomBomByStatusId(
                        rtCfgStatusInfoDO.getStatusid(), otype);
                if (IterUtil.isEmpty(dspfMbomBomDOs)) {
                    stringBuffer.append("当前需求状态表【" + rtCfgStatusInfoDO.getStatuscode() + "】没有BOM头部数据,");
                }

                dspfMbomBomDOs.stream().forEach(i -> {
                    List<DspfMbomDetailDO> dspfMbomDetailDOS = dspfMbomDetailMapper.selectDspfMbomDetailListByBomid(
                            i.getBomid(), Integer.valueOf(i.getOtype()));
                    this.isMaterialEffective(rtCfgStatusInfoDO, dspfMbomDetailDOS, stringBuffer);
                });


                if (stringBuffer.length() != 0) {
                    throw RTErrorCodeEnum.WORK_FLOW_EXECUTE_EXCEPTION.getException(stringBuffer.toString());
                }
            }

        }
    }

    /**
     * 获取当前流程节点名称
     *
     * @param flowTaskRecordList
     * @return
     */
    private String getOtypeByTaskName(List<FlowTaskRecord> flowTaskRecordList) {
        FlowTaskRecord flowTaskRecord = flowTaskRecordList.get(flowTaskRecordList.size() - 1);
        String taskName = flowTaskRecord.getTaskName();
        //根据节点名称定义otype 0动力1终端2传动
        String otype = "";
        if (taskName.contains("动力")) {
            otype = "0";
        }
        if (taskName.contains("终端")) {
            otype = "1";
        }
        if (taskName.contains("传动")) {
            otype = "2";
        }
        return otype;
    }


    @Override
    public void workBomZdVerify(BigInteger finalWorkFlowContainerId) {
        WorkFlowContainerView workFlowContainerView = typlmWorkFlowContainerService
                .getWorkFlowContainerDetailByPrimaryKey(
                        finalWorkFlowContainerId);
        List<IdentifierEntity> flowList = new ArrayList<>();
        if ((workFlowContainerView instanceof WorkFlowObjectPackage)) {
            log.info("当前流程属于普通流程----》成品BOM指定校验");
            WorkFlowObjectPackage workFlowObjectPackage = (WorkFlowObjectPackage) workFlowContainerView;
            List<FlowObject> flowObjectList = workFlowObjectPackage.getFlowObjectList();
            if (CollUtil.isNotEmpty(flowObjectList)) {
                flowList = flowObjectList.stream().map(
                        m -> new IdentifierEntity(m.getRefObjectOid(), m.getRefObjectOtype())).distinct().collect(
                        Collectors.toList());
                BigInteger oid = flowList.get(0).getOid();
                RtCfgStatusDTO rtCfgStatusDTO = new RtCfgStatusDTO();
                rtCfgStatusDTO.setOid(String.valueOf(oid));
                RtCfgStatusInfoDO rtCfgStatusInfoDO = rtCfgStatusInfoMapper.selectByStatusCode(rtCfgStatusDTO);

                //异常汇总字符串
                StringBuffer stringBuffer = new StringBuffer("");

                List<DspfMbomBomDO> dspfMbomBomDOS = dspfMbomBomMapper.selectDspfMbomBomByStatusId(
                        rtCfgStatusInfoDO.getStatusid(), null);
                if (IterUtil.isEmpty(dspfMbomBomDOS)) {
                    stringBuffer.append("当前需求状态表【" + rtCfgStatusInfoDO.getStatuscode() + "】没有BOM头部数据,");
                }
                List<DspfMbomDetailDO> listZD = new ArrayList<>();
                if (IterUtil.isNotEmpty(dspfMbomBomDOS)) {
                    for (DspfMbomBomDO dspfMbomBomDO : dspfMbomBomDOS) {
                        List<DspfMbomDetailDO> list = dspfMbomDetailMapper.selectDspfMbomDetailListByBomid(
                                dspfMbomBomDO.getBomid(), null);
                        list.stream().forEach(i -> {
                            Map<String, Object> params = new HashMap<>();
                            params.put("materialCode", i.getMaterialcode());
                            params.put("status", 1);
                            Map<String, Object> map = rtZdService.queryZdInfo(params);
                            List zdList = (List) map.get("list");
                            if (IterUtil.isEmpty(zdList)) {
                                listZD.add(i);
                            }
                        });
                    }
                }
                if (IterUtil.isNotEmpty(listZD)) {
                    String materialCodes = listZD.stream()
                            .map(DspfMbomDetailDO::getMaterialcode)
                            .filter(Objects::nonNull)
                            .collect(Collectors.joining(","));
                    stringBuffer.append("当前需求状态表【" + rtCfgStatusInfoDO.getStatuscode() + "】还有未指定物料," + materialCodes);
                }

                if (stringBuffer.length() != 0) {
                    throw RTErrorCodeEnum.WORK_FLOW_EXECUTE_EXCEPTION.getException(stringBuffer.toString());
                }
            }

        }
    }

    @Override
    public ResponseResult getFlowDataByFlowCode(String flowCode) {
        Map map = rtCfgStatusInfoMapper.getFlowDataByFlowCode(flowCode);
        return ResponseResult.success(map, "请求成功");
    }

    /**
     * 校验成品BOM里面的物料是否有效
     *
     * @param list
     */
    private void isMaterialEffective(RtCfgStatusInfoDO rtCfgStatusInfoDO, List<DspfMbomDetailDO> list,
                                     StringBuffer stringBuffer) {

        /*
         * 成品BOM物料校验逻辑
         *   1.校验物料是否有效，是否非售后件
         *   2.校验物料扩展属性是否跟需求状态表填写的值一样
         *   3.bom结构是否重复
         *   4.认证相关的校验
         *   5.检查物料图纸是否出图，出图是否正确（已转移到成品码生成节点）
         * */
        List<DspfMbomDetailDO> filteredListNull = list.stream()
                .filter(item -> item.getMaterialcode() == null || item.getMaterialcode().isEmpty())
                .collect(Collectors.toList());
        if (IterUtil.isNotEmpty(filteredListNull)) {
            stringBuffer.append("成品BOM结构存在为空值的物料数据,");
        }
        List<DspfMbomDetailDO> filteredList = list.stream()
                .filter(item -> item.getMaterialcode() != null && item.getMaterialcode().length() == 18)
                .collect(Collectors.toList());
        filteredList.stream().forEach(i -> {
            String partnumber = i.getMaterialcode();
            //            List<PartMasterDO> partMasterDOS = typlmPartService.queryPartMasterByPartNumber(partnumber);
            //            PartMasterDO partMasterDO = partMasterDOS.get(0);
            //            PartDetailsVO partDetailsVO = typlmPartService.queryPartDetails(partMasterDO.getOid(), partMasterDO.getOtype());
            PartDO partDO = typlmPdmPartService.queryLastPartDoByPartNumber(partnumber);
            String lifecycleState = partDO.getLifecyclestagekey();
            if (!"RELEASED".equals(lifecycleState)) {//已发布
                stringBuffer.append("物料【" + partnumber + "】不是已发布状态,");
            }
            TyplmAttributeServiceImpl bean = SpringUtil.getBean(TyplmAttributeServiceImpl.class);
            Map<String, List<String>> ibaAttributeMap = bean.getIbaAttributeMap(partDO.getOid(), partDO.getOtype());
            log.info("物料IBA属性={}", ibaAttributeMap.toString());
            if (!MapUtil.isEmpty(ibaAttributeMap) && !IterUtil.isEmpty(
                    ibaAttributeMap.get("ManufacturingProperties")) &&
                    !StrUtil.isEmpty(ibaAttributeMap.get("ManufacturingProperties").get(0))) {
                String manufacturingProperties = ibaAttributeMap.get("ManufacturingProperties").get(0);
                if ("6".equals(manufacturingProperties)) {
                    stringBuffer.append("物料【" + partnumber + "】为售后件,");
                }
            }

            //校验成品物料扩展属性值是否和需求表一致
            this.verifyKzsx(rtCfgStatusInfoDO, ibaAttributeMap, partnumber, stringBuffer);
        });

        //校验物料是否满足认证要求
//        this.verifyRz(rtCfgStatusInfoDO, list, stringBuffer);
        this.verifyRzV2(rtCfgStatusInfoDO, list, stringBuffer);
        //校验BOM结构是否重复
        this.verifyBomRepeat(rtCfgStatusInfoDO, list, stringBuffer);

    }

    /**
     * 校验当前需求状态表下的BOM结构是否重复
     *
     * @param rtCfgStatusInfoDO
     * @param list
     */
    private void verifyBomRepeat(RtCfgStatusInfoDO rtCfgStatusInfoDO, List<DspfMbomDetailDO> list,
                                 StringBuffer stringBuffer) {

        List<String> bomIds = list.stream()
                .map(DspfMbomDetailDO::getBomid)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());

        List<String> kIds = list.stream()
                .map(DspfMbomDetailDO::getKid)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());

        Integer count = dspfMbomDetailMapper.selectBomRepeat(bomIds, kIds);
        if (count > 1) {
            stringBuffer.append("当前需求状态表【" + rtCfgStatusInfoDO.getStatuscode() + "】BOM结构重复");
        }

    }

    /**
     * 校验物料是否满足认证要求（弃用）
     *
     * @param rtCfgStatusInfoDO
     * @param list
     * @param stringBuffer
     */
    private void verifyRz(RtCfgStatusInfoDO rtCfgStatusInfoDO, List<DspfMbomDetailDO> list, StringBuffer stringBuffer) {

        /*
         * 认证+动力备案型号+客户编码+开发令   校验机型和零部件备案是否满足要求
         *   1.根据认证类型+动力备案型号锁定机型和零部件备案数据
         *   2.根据客户编码与开发令锁定备案零部件（注：当客户编码数据为空的时候是满足所有客户编码的）
         *   3.根据第二步锁定到备案零部件数据
         *   4.根据零部件编码的品类码去bom表查询有没有此品类码的数据，如果有就截取物料编码前11位和零件号前11位相比较
         * */

        //获取认证信息
        String rzValue = rtCfgStatusInfoMapper.selectRzByInfoid(rtCfgStatusInfoDO.getStatusid());
        if (StrUtil.isEmpty(rzValue)) {
            stringBuffer.append("需求状态表" + rtCfgStatusInfoDO.getStatuscode() + "无认证信息,");
        }
        //获取动力备案机型
        String powerRegistrationModel = rtCfgStatusInfoDO.getClientrecordtype();
        if (StrUtil.isEmpty(powerRegistrationModel)) {
            stringBuffer.append("需求状态表" + rtCfgStatusInfoDO.getStatuscode() + "无动力备案机型,");
        }

        if (StrUtil.isNotEmpty(rzValue) && StrUtil.isNotEmpty(powerRegistrationModel)) {
            // 拆分认证要求
            String certVerificatyType = RTPlmConstant.certVerificatyType;
            List<String> coerceCertList = Arrays.asList(certVerificatyType.split(","));
            List<String> certificationList = new ArrayList<>();
            if (StringUtils.isNotBlank(rzValue) && !rzValue.equals("无认证")) {
                String[] certs = rzValue.replaceAll(";", "+").split("\\+");
                for (String cert : certs) {
                    if (!cert.isEmpty()) {
                        if (coerceCertList.contains(cert)) {
                            certificationList.add(cert);
                        }
                    }
                }
            }
            // 查询认证信息
            List<RtCertFiledVO> certInfoList = rtCertFiledMapper.queryCertByCtypeAndModel(certificationList,
                                                                                          powerRegistrationModel);
            // 7. 比较并验证认证
            List<PartDO> clearChildParts = new ArrayList<>();
            for (DspfMbomDetailDO dspfMbomDetailDO : list) {
                if (StrUtil.isNotEmpty(dspfMbomDetailDO.getMaterialcode())) {
                    PartDO partDO = typlmPdmPartService.queryLastPartDoByPartNumber(dspfMbomDetailDO.getMaterialcode());
                    partDO.setPartnumber(dspfMbomDetailDO.getMaterialcode());
                    clearChildParts.add(partDO);
                }
            }
            Map<String, List<PartDO>> resultMap = this.traverseAndValidateCertification(clearChildParts);
            this.comparePartCodeAndPatternCode(powerRegistrationModel, resultMap, certInfoList, certificationList,
                                               stringBuffer);
        }

    }

    /**
     * 校验物料是否满足认证要求V2
     *
     * @param rtCfgStatusInfoDO
     * @param list
     * @param stringBuffer
     */
    private void verifyRzV2(RtCfgStatusInfoDO rtCfgStatusInfoDO, List<DspfMbomDetailDO> list,
                            StringBuffer stringBuffer) {

        /*
         * 认证+动力备案型号+客户编码+开发令   校验机型和零部件备案是否满足要求
         *   1.根据认证类型+动力备案型号锁定机型和零部件备案数据
         *   2.根据客户编码与开发令锁定备案零部件（注：当客户编码数据为空的时候是满足所有客户编码的）
         *   3.根据第二步锁定到备案零部件数据
         *   4.根据零部件编码的品类码去bom表查询有没有此品类码的数据，如果有就截取物料编码前11位和零件号前11位相比较
         * */

        //获取认证信息
        String rzValue = rtCfgStatusInfoMapper.selectRzByInfoid(rtCfgStatusInfoDO.getStatusid());
        if (StrUtil.isEmpty(rzValue)) {
            stringBuffer.append("需求状态表" + rtCfgStatusInfoDO.getStatuscode() + "无认证信息,");
        }
        //获取动力备案机型
        String powerRegistrationModel = rtCfgStatusInfoDO.getClientrecordtype();
        if (StrUtil.isEmpty(powerRegistrationModel)) {
            stringBuffer.append("需求状态表" + rtCfgStatusInfoDO.getStatuscode() + "无动力备案机型,");
        }
        List<String> rzList = Arrays.asList(rzValue.split("\\+"));
        for (String rz : rzList) {
            //锁定机型和零部件信息
            RtCertFiledDO rtCertFiled = new RtCertFiledDO();
            rtCertFiled.setCtype(rz);
            rtCertFiled.setModel(powerRegistrationModel);
            rtCertFiled.setState("RELEASED");//生效
            List<RtCertFiledDO> rtCertFileList = rtCertFiledService.selectRtCertFiledList(rtCertFiled);
            if(IterUtil.isNotEmpty(rtCertFileList)){
                for (RtCertFiledDO certFiledDO:rtCertFileList){
                    RTCertFiledFormDTO rtCertFiledFormDTO = rtCertFiledService.selectRtCertFiledAllDataById(
                            certFiledDO.getId());
                    //根据客户编码与开发令锁定备案零部件数据
                    List<RtCertFiledCustomerDO> customerlist = rtCertFiledFormDTO.getCustomerlist();
                    List<RtCertFiledCustomerDO> filteredList = customerlist.stream()
                            .filter(customer -> rtCfgStatusInfoDO.getCustomecode().equals(customer.getKhmc()) ||
                                    (customer.getKhmc() == null || customer.getKhmc().isEmpty()))
                            .collect(Collectors.toList());
                    List<RtCertFiledRatoModelsDO> ratoModelslist = rtCertFiledFormDTO.getRatoModelslist();
                    List<RtCertFiledRatoModelsDO> filteModelList = ratoModelslist.stream()
                            .filter(model -> rtCfgStatusInfoDO.getDevcode().equals(model.getDevCode()))
                            .collect(Collectors.toList());
                    if(IterUtil.isNotEmpty(filteredList)&&IterUtil.isNotEmpty(filteModelList)){
                        //获取备案零部件数据开始进行校验
                        List<RtCertFiledPartinfoDO> partlist = rtCertFiledFormDTO.getPartlist();
                        if(IterUtil.isNotEmpty(partlist)){
                            List<String> partCodes = partlist.stream()
                                    .map(RtCertFiledPartinfoDO::getPartCode)
                                    .filter(Objects::nonNull)
                                    .collect(Collectors.toList());
                            List<DspfMbomDetailDO> filteMomDetaList = list.stream()
                                    .filter(item -> {
                                        String materialCode = item.getMaterialcode();
                                        if (materialCode == null || materialCode.length() < 5) {
                                            return false;
                                        }
                                        String prefix = materialCode.substring(0, 5);
                                        return partCodes.contains(prefix);
                                    })
                                    .collect(Collectors.toList());
                            if(IterUtil.isNotEmpty(filteMomDetaList)){
                                for (DspfMbomDetailDO dspfMbomDetailDO:filteMomDetaList){
                                    String materia = dspfMbomDetailDO.getMaterialcode().substring(0, 11);
                                    for (RtCertFiledPartinfoDO rtCertFiledPartinfoDO:partlist){
                                        String partNo = rtCertFiledPartinfoDO.getPartNo().substring(0, 11);
                                        if(!materia.equals(partNo)){
                                            stringBuffer.append("认证:"+rz+",动力备案机型:"+powerRegistrationModel
                                                                        +",开发令:"+rtCfgStatusInfoDO.getDevcode()
                                                                        +",机型:"+rtCfgStatusInfoDO.getProducttype()
                                                                        +"下的零件号【"+rtCertFiledPartinfoDO.getPartNo()
                                                                        +"】与BOM结构里面的"+dspfMbomDetailDO.getMaterialcode()+"不匹配,");
                                        }
                                    }
                                }
                            }
                        }
                    }

                }
            }
        }

    }

    private Map<String, List<PartDO>> traverseAndValidateCertification(List<PartDO> partBomTreeList) {
        Map<String, List<PartDO>> resultMap = new HashMap<String, List<PartDO>>();
        for (PartDO partDO : partBomTreeList) {
            // 获取对象编号
            String objectNumber = partDO.getPartnumber();
            // 先匹配前五位
            String partCode = objectNumber.substring(0, 5);
            List<PartDO> patternList = null;
            if (resultMap.containsKey(partCode)) {
                patternList = resultMap.get(partCode);
                if (!patternList.contains(partDO)) {
                    patternList.add(partDO);
                }
            } else {
                patternList = new ArrayList<>();
                patternList.add(partDO);
            }
            resultMap.put(partCode, patternList);
        }
        return resultMap;
    }

    private void comparePartCodeAndPatternCode(String PowerRegistrationModel,
                                               Map<String, List<PartDO>> bomMap, List<RtCertFiledVO> certInfoList,
                                               List<String> certificationList, StringBuffer stringBuffer) {
        // 错误信息
        String error = "";
        // 遍历验证每个部件是否备案
        for (String partCode : bomMap.keySet()) {
            List<PartDO> patternList = bomMap.get(partCode);
            List<RtCertFiledVO> tempList = new ArrayList<>();
            // 获取当前partCode对应的认证信息
            if (certInfoList.size() > 0) {
                tempList = certInfoList.stream().filter(item -> item.getPartCode().equals(partCode)).collect(
                        Collectors.toList());
            }
            if ("18100".equals(partCode)) {
                //消声器部件检查逻辑
                for (PartDO partDO : patternList) {
                    String partNumber = partDO.getPartnumber();
                    String patternCode = partNumber.substring(0, 11);
                    //当18100无备案
                    for (int j = 0; j < certificationList.size(); j++) {
                        String cert = certificationList.get(j);
                        int index = 0;
                        for (int i = 0; i < tempList.size(); i++) {
                            RtCertFiledVO filedVO = tempList.get(i);
                            String tempNo = filedVO.getPartNo();
                            String tempType = filedVO.getCType();
                            if (!tempNo.equals(patternCode) || !cert.equals(tempType)) {
                                index++;
                            }
                        }
                        if (index == tempList.size()) {
                            //根据18100物料料描述获取18160图号
                            PartDetailsVO detailsVO = this.typlmPdmPartService.queryPartDetailsForCO(partDO.getOid(),
                                                                                                     partDO.getOtype());
                            String desc = detailsVO.getDescription();
                            if (StringUtils.isNotBlank(desc) && desc.contains("消声器体打刻")) {
                                String tempNumber = desc.substring(desc.indexOf("消声器体打刻"),
                                                                   desc.indexOf("消声器体打刻") + 6 + 11);
                                //获取18160的备案零部件数据
                                List<RtCertFiledVO> filterCertVOS = certInfoList.stream().filter(
                                        item -> "18160".equals(item.getPartCode())).collect(Collectors.toList());
                                //检查消声器体的是否备案
                                for (int k = 0; k < certificationList.size(); k++) {
                                    String cert2 = certificationList.get(k);
                                    int index2 = 0;
                                    for (int i = 0; i < filterCertVOS.size(); i++) {
                                        RtCertFiledVO filedVO = filterCertVOS.get(i);
                                        String tempNo = filedVO.getPartNo();
                                        String tempType = filedVO.getCType();
                                        if (!tempNo.equals(tempNumber) || !cert2.equals(tempType)) {
                                            index2++;
                                        }
                                    }
                                    if (index2 == filterCertVOS.size()) {
                                        stringBuffer.append(
                                                "备案机型为" + PowerRegistrationModel + "下的" + tempNumber + "未在" + cert2 + "认证里面备案，请处理!");
                                    }
                                }
                            } else {
                                stringBuffer.append(
                                        "备案机型为" + PowerRegistrationModel + "下的" + partNumber + "未在" + cert + "认证里面备案，请处理!");
                            }
                        }
                    }
                }
            } else {
                //其它
                for (PartDO partDO : patternList) {
                    String partNumber = partDO.getPartnumber();
                    String patternCode = partNumber.substring(0, 11);
                    for (int j = 0; j < certificationList.size(); j++) {
                        String cert = certificationList.get(j);
                        int index = 0;
                        for (int i = 0; i < tempList.size(); i++) {
                            RtCertFiledVO filedVO = tempList.get(i);
                            String tempNo = filedVO.getPartNo();
                            String tempType = filedVO.getCType();
                            if (!tempNo.equals(patternCode) || !cert.equals(tempType)) {
                                index++;
                            }
                        }
                        if (index == tempList.size()) {
                            stringBuffer.append(
                                    "备案机型为" + PowerRegistrationModel + "下的" + partNumber + "未在" + cert + "认证里面备案，请处理!");
                        }
                    }
                }
            }
        }
    }

    /**
     * 校验需求状态表填写值（属性拼接）与物料扩展属性是否一致
     *
     * @param rtCfgStatusInfoDO
     * @param ibaAttributeMap
     * @param partnumber
     * @param stringBuffer
     */
    private void verifyKzsx(RtCfgStatusInfoDO rtCfgStatusInfoDO, Map<String, List<String>> ibaAttributeMap,
                            String partnumber, StringBuffer stringBuffer) {

        /*
         * 校验逻辑
         *   1.根据状态状态表id查询填写内容
         *   2.根据物料品类、内部名称查询扩展属性值进行比对
         * */
        //获取品类码
        String partsCode = partnumber.substring(0, 5);
        List<SubModuleDataDTO> subModuleDataDTOS = rtCfgStatusInfoMapper.selectModuleDataByStatusId(partsCode,
                                                                                                    rtCfgStatusInfoDO
                                                                                                            .getStatusid());
        if (IterUtil.isNotEmpty(subModuleDataDTOS)) {
            for (SubModuleDataDTO subModuleDataDTO : subModuleDataDTOS) {
                String selectvaluename = subModuleDataDTO.getSelectvaluename();
                String descrCode = subModuleDataDTO.getDescrCode();
                String descrName = subModuleDataDTO.getDescrName();
                List<String> list = ibaAttributeMap.get(descrCode);
                if (IterUtil.isEmpty(list)) {
                    stringBuffer.append("此物料编码【" + partnumber + "】扩展属性中没有【" + descrName + "】的值,");
                } else {
                    String value = list.get(0);
                    if (!selectvaluename.equals(value)) {
                        stringBuffer.append(
                                "此物料编码【" + partnumber + "】扩展属性【" + descrName + "】的值" + value + "与需求状态表的值不一致,");
                    }
                }
            }
        }

    }

    @Override
    public void parallelNodeCheckListener(BigInteger workFlowContainerId, String nodeIds) {
        WorkFlowContainerView workFlowContainerView = typlmWorkFlowContainerService
                .getWorkFlowContainerDetailByPrimaryKey(
                        workFlowContainerId);
        List<FlowTaskRecord> flowTaskRecordList = workFlowContainerView.getFlowTaskRecordList();
        List<UserTaskDTO> userTaskList = workFlowContainerView.getUserTaskList();
        if (StrUtil.isNotEmpty(nodeIds)) {
            List<String> list = Arrays.asList(nodeIds.split(","));
            list.stream().forEach(nodeId -> {
                List<UserTaskDTO> userTaskDTOList = userTaskList.stream().filter(
                        userTaskDTO -> userTaskDTO.getId().equals(nodeId)).collect(Collectors.toList());
                if (IterUtil.isNotEmpty(userTaskDTOList.get(0).getUserList())) {
                    if (CollUtil.isEmpty(userTaskDTOList)) {
                        throw RTErrorCodeEnum.WORK_FLOW_EXECUTE_EXCEPTION.getException("节点[" + nodeId + "]在当前流程不存在");
                    }
                    boolean flag = false;
                    for (FlowTaskRecord flowTaskRecord : flowTaskRecordList) {
                        if (flowTaskRecord.getTaskDefId().equals(nodeId)) {
                            String operateName = flowTaskRecord.getOperateName();
                            if ("通过".equals(operateName) || "批准".equals(operateName) || "同意".equals(operateName)) {
                                flag = true;
                            }
                        }
                    }

                    if (!flag) {
                        UserTaskDTO userTaskDTO = userTaskDTOList.get(0);
                        String name = userTaskDTO.getName();
                        throw RTErrorCodeEnum.WORK_FLOW_EXECUTE_EXCEPTION.getException(
                                "当前节点不可提交，需要等待[" + name + "]提交后，才可提交");
                    }
                }

            });
        }

    }

    @Override
    public ResponseResult getTransitOrder(RtCfgDspfDemandMainQueryDTO dto) {

        if (StrUtil.isEmpty(dto.getmBomCode())) {
            throw RTErrorCodeEnum.WORK_FLOW_EXECUTE_EXCEPTION.getException("成品码为空，请先选择成品码");
        }

        List<TransitOrderResponseVO> trList = new ArrayList<>();

        //获取CRM订单接口数据
        CrmApiQueryDTO queryDTO = new CrmApiQueryDTO(dto);
        CrmApiResponseVO crmVO = crmApiService.getCRMOrderList(queryDTO);
        if (crmVO.getCode().intValue() == 200) {
            List<CrmApiResponseVO.DdDataVO> crmList = crmVO.getData();
            if (IterUtil.isNotEmpty(crmList)) {
                crmList.stream().forEach(i -> {
                    TransitOrderResponseVO transitOrderResponseVO = new TransitOrderResponseVO(i);
                    trList.add(transitOrderResponseVO);
                });
            }

        }

        //获取sap订单接口数据
        RestAdapterQasDTO sapDto = new RestAdapterQasDTO();
        List<String> list = Arrays.asList(dto.getmBomCode().split(","));
        List<RestAdapterQasDTO.Vbeln> vbelnList = new ArrayList<>();
        if (IterUtil.isNotEmpty(list)) {
            list.stream().forEach(i -> {
                RestAdapterQasDTO.Vbeln vbeln = new RestAdapterQasDTO.Vbeln();
                vbeln.setVBELN(i);
                vbelnList.add(vbeln);
            });
            RestAdapterQasDTO.ItVbeln itVbeln = new RestAdapterQasDTO.ItVbeln();
            itVbeln.setItem(vbelnList);
            sapDto.setIT_VBELN(itVbeln);
        }
        RestAdapterEsReturDTO restAdapterEsReturDTO = sapApiService.restAdapterQas(sapDto);
        if (restAdapterEsReturDTO.getEs_RETURN() != null && "S".equals(
                restAdapterEsReturDTO.getEs_RETURN().getTYPE())) {
            if (IterUtil.isNotEmpty(restAdapterEsReturDTO.getEt_TAB().getItem())) {
                List<RestAdapterEsReturDTO.Tab> item = restAdapterEsReturDTO.getEt_TAB().getItem();
                item.stream().forEach(i -> {
                    TransitOrderResponseVO transitOrderResponseVO = new TransitOrderResponseVO(i);
                    trList.add(transitOrderResponseVO);
                });
            }

        }

        //获取MOM订单接口数据
        RestAdapterMomOrderDTO momOrderDTO = new RestAdapterMomOrderDTO(dto);
        MomApiResponseVO order = momApiService.getOrder(momOrderDTO);
        if ("S".equals(order.getStatus())) {
            if (IterUtil.isNotEmpty(order.getDetail())) {
                List<MomApiResponseVO.MomOrderDTO> detail = order.getDetail();
                detail.stream().forEach(i -> {
                    TransitOrderResponseVO transitOrderResponseVO = new TransitOrderResponseVO(i);
                    trList.add(transitOrderResponseVO);
                });
            }
        }


        return ResponseResult.success(trList, "获取成功");
    }


}
